I have a problem for writing tests for conditional cases. One of the test uses the api in 'before' (beforeAll) function to create an object, and then in test the object that was created is not shown in searching result sometimes. I was using puppeteer before. I can let the page reload until the object shows in the search result. However, there is no way for me to do the same thing. I was thinking of using cy.get and then checking the response. For instance, (cy.get('sth').then(s1 => {do something like cy.reload()})).
Then, I found out that s1 always kept the same after reload. So, I am stuck. Hope someone give me a hand to it. If the description is not clear, please the my another post below. Thanks
Im sorry but the problem is in your before function. You gotta start it only when you are done preparing your environments to run your test.
const createPerson = (params, done)=>{
cy.request({// create people here}).then(({people})=>{
done(undefined, {people});
})
}
before((done)=> {
createPerson({}, (err, {people})=>{
cy.visit('mywebsite);
login({}, done); // this should be async as well
});
})
it('search person I created by calling api', () => {
//if you data is not cached, at this point you will have the people populated in your screen.
cy.get('.search')
.type('person's name{enter}');
cy.get(':nth-child(1) > resulttable').click();
Based on what I'm gathering from your post, I think something like this may help:
cy.get('some.selector').then(elem => {
// ...
});
cy.reload();
cy.get('some.selector').then(elem => {
// run code on element after reloading...
});
If this does not answer your question, please consider making a minimal, complete and verifiable example.
My bad. I didn't explain my problem well. The problem is not in before() function. In before() function, I call post API to create persons.
Then, I will use those persons created in before() function in each of my tests.
The code would look like:
before(()=> {createPerson(); cy.visit('mywebsite); login();} )
it('search person I created by calling api', () => {
cy.get('.search')
.type('person's name{enter}');
cy.get(':nth-child(1) > resulttable').click();
Here is the problem. I can't find the person in search result since the data needs time to be passed. Then, the test fails.
So, I need reload the page (The page is searching result page) by calling
cy.reload();
However, I don't know how many reload I need to call above to let the person show up in the searching result.
The current solution I used is to cy.wait(30000). wait 30 seconds.
So, I am wondering how I am going to do right now.
Related
I am most likely overcomplicating this. I am fairly confident with MySQL but never used transactions before. I know the concept is begin(), do stuff, commit() or rollback() on a failure and I am pretty sure I can structure that with ease.
What I want to find out is during a transaction I want to update a table then use that updated value in another query during the same transaction. Heres an outline:
begin()
INSERT
SELECT FROM INSERT
UPDATE BASED ON SELECT
commit()
Obviously I have slimmed down the code here and this on its own means nothing. I would like to know if this concept works before I go too deep into transactions and find it doesn't work.
My actual transaction is going to be about 5 times larger and parts of it rely on other parts of the unfinished transaction as above.
I am using Laravel so my code uses DB::beginTransaction() DB::commit() and DB::rollback() if this makes any difference to the question.
So, the simple answer to this is yes.
I ran through a number of tests with the code I had been developing and this is the state, at least in my case.
DB::beingTransaction()
Now we do our thing. ALL STATEMENTS HERE ARE RELATIVE TO EACH OTHER AND PERFORMED IN ORDER.
DB::commit()
This then runs all the statements in order as long as the simulated run through was a success
DB::rollback()
This is called on ALL methods where changes could potentially fail within a try catch block
So let me provide a working (simplified) Laravel example to demonstrate the basics:
public function store(Request $request)
{
DB::beginTransaction();
try
{
if(!$this->setAuthorisation($request))
throw new Exception('Failed to set authorisation');
DB::commit();
return response()->json(['status' => 'OK'], 200);
}
catch (Exception $exception)
{
DB::rollBack();
return response()->json(['status' => 'Failed', 'error'=>$exception->getMessage()], 500);
}
}
Now from here we can access the changes made in the setAuthorisation() method say in a getAuthorisation() method and then apply the data from $data = getAuthorisation() to another set of code say for example in setData($data).
The entire transaction works in order of simulated events before commiting so it "applies" the changes before "actually applying" the changes. Its really hard to explain any more than that so I hope this answers my own question.
I'm using the World of warcraft API. And I want to find an EventMessageFilter. I can do so by calling
ChatFrame_GetMessageEventFilters("event")
And to do this I have to pass a chat event, in my case CHAT_MSG_WHISPER_INFORM.
So according to the API located over at
http://wowprogramming.com/docs/api/ChatFrame_GetMessageEventFilters
This function will return a table. So I named the table and tried to print its content with this code
local myNewTable = filterTable = ChatFrame_GetMessageEventFilters("CHAT_MSG_WHISPER_INFORM")
for i in pairs(myNewTable) do
print(asd[i])
end
And this then prints out something like
function: 00000312498vn27842934c4
I have checked with
type(asd[i])
and it really is a function. But how can I get the content of it? How do I handle it?
I want to find an EventMessageFilter
Can you elaborate? Whose filter are you looking for and what do you intend to do with it?
it really is a function.
That's what this API does: returns a list of functions that are registered as filters for a particular message type (via ChatFrame_AddMessageEventFilter).
But how can I get the content of it?
You can't. The WoW API doesn't offer you any facilities for decompiling functions.
If your intention is to filter chat messages yourself, you don't need to call this function at all. Just call ChatFrame_AddMessageEventFilter to add your filter.
So I managed to solve my problem by removing to current filters that have been put in place by another addon and then just add my own filter. As Mud pointed out. GMEF was supposed to return functions. I now see how this makes sense. But now I have made the code to remove the functions. If you want to re-add them later on, just store them in a variable until you are done but I won't include this in my answer. I also feel like my answer is kinda half off-topic ish. But to answer my own question. It is supposed to return functions and you can't see the contents of these functions. This is the code I used to remove the functions that were put in there by another addon.
function rekkFilters()
local myFilters = ChatFrame_GetMessageEventFilters("CHAT_MSG_WHISPER_INFORM")
for i in pairs(myFilters) do
ChatFrame_RemoveMessageEventFilter("CHAT_MSG_WHISPER_INFORM", myFilters[i])
end
end
local myFilters = ChatFrame_GetMessageEventFilters("CHAT_MSG_WHISPER_INFORM")
rekkFilters()
local myFilters = ChatFrame_GetMessageEventFilters("CHAT_MSG_WHISPER_INFORM")
if myFilters[1] ~= nil then
rekkFilters()
end
I use Dalek to test my sample to-do application written with help of Mithril framework.
Everything goes fine until .type() comes in.
If I .type() something in input that have bi-directional binding m.prop with m.withAttr and then assert values of that field i get strage behaviour. Instead "test title" I get "tsttle". It seems that test are running too quickly for Mithril to capture changes and render them back to DOM.
If assertions for input equality is removed — all works just fine.
Is there any workaround, can I slow down type process?
P.S. I use Chrome browser as test runner.
That definitely is an interesting issue, the problem is though, that Dalek can't control the speed of the letters typed. This is due to the fact that the JSON-Wire Protocol does not give us a way to handle that, see here
One thing you could do, even if it seems like overkill, is to add a long function chain with explicit waits, like this:
.type('#selector', 'H')
.wait(500)
.type('#selector', 'e')
.wait(500)
.type('#selector', 'l')
.wait(500)
.type('#selector', 'l')
.wait(500)
.type('#selector', 'o')
You also could go ahead & write a utility function that handles that for you
function myType (selector, keys, test, wait) {
var keysArr = keys.split('');
keysArr.forEach(function (key) {
test.type(selector, key).wait(wait);
});
return test;
}
And then use it in your test like this:
module.exports = {
'my test': function (test) {
test.open('http://foobar.com');
myType('#selector', 'Hello', test, 500);
test.done();
}
};
Mithril, as of when I'm writing this, does a re-render on onkey* events. An option to avoid this is coming.
You could use attr::config at present to handle the onkey* events as this will not cause a rerender. For example:
m('input', {config: addHandler});
function addHandler (el, isInitialized, context) {
if (!isinitialized) {
el.addEventListener('onkeyup', keyHandler, false);
}
}
function keyHandler (event) { /* do something with key press */ }
Its possible {config: addHandler, onchange: m.withAttr('value', mpropData)} will do what you want, but I don't know Dalek. If its doesn't, then you can consider updating mpropData inside keyHandler.
Mithril renders asynchronously in response to event handlers (basically so that related groups of events like keypress/input all get a chance to run before redrawing)
You could try a few things:
if you have access to your data model from your test, you could run your assertion against that model value (which is updated synchronously), as opposed to using the DOM value which only gets updated on the next animation frame
otherwise, you could force a synchronous redraw by explicitly calling m.render (yes, render, not redraw) before running the assertion, to ensure the view is actually in sync w/ the data model
alternatively, you could try waiting for one animation frame (or two) before running the assertion
I am having difficulty finding the answer to this question - I suspect because I'm probably not using the right terminology. I am using Meteor.
Here is what I am trying to accomplish:
Function A - returns the flickr userID based on userAPI and username
Function B - uses the userID generated by Function A
The problem I have is that Function B is completing before Function A has had a chance to retrieve the information from Flickr.
What is the best manner to delay Function B and somehow connect it to the successful completion of Function A?
Since Meteor is an async framework built on top of Node, you have to think a little differently then you're probably used to. One way to do this would be as follows.
var a = function(cb){
var flickerId = getFlickerId();
cb(flickerId);
};
var b = function(flickerId){
//do something with the id
};
//call it
a(b);
I'm guessing you're using some framework that gets the flicker info for you. That framework probably has a function call which takes a callback like function 'a' above.
As the callback stack grows deeper and deeper this sort of code can become confusing. Once you have mastered the above, I suggest looking into https://github.com/kriskowal/q for a cleaner solution.
Previously I was PHP developer so this question might be stupid to some of you.
I am using mysql with node js.
client.query('SELECT * FROM users where id="1"', function selectCb(err, results, fields) {
req.body.currentuser = results;
}
);
console.log(req.body.currentuser);
I tried to assign the result set (results) to a variable (req.body.currentuser) to use it outside the function, but it is not working.
Can you please let me know a way around it.
The query call is asynchronous. Hence selectCb is executed at a later point than your console.log call. If you put the console.log call into selectCb, it'll work.
In general, you want to call everything that depends on the results of the query from the selectCb callback. It's one of the basic architectural principles in Node.JS.
The client.query call, like nearly everything in node.js, is asynchronous. This means that the method just initiates a request, but execution continues. So when it gets to the console.log, nothing has been defined in req.body.currentuser yet.
You can see if you move the console log inside the callback, it will work:
client.query('SELECT * FROM users where id="1"', function selectCb(err, results, fields) {
req.body.currentuser = results;
console.log(req.body.currentuser);
});
So you need to structure your code around this requirement. Event-driven functional programming (which is what this is) can be difficult to wrap your head around at first. But once you get it, it makes a lot of sense.