Ember component, how to wait for random jQuery plugin initialization? - javascript

I have an Ember component wrapping a random jQuery plugin.
setUp: on('didInsertElement', function() {
scheduleOnce('afterRender', () => {
this.$().datetimepicker();
});
})
The plugin takes about 250ms to show up on screen, which causes me to write acceptance tests like so:
test('clicking toggles visibility', function(assert) {
let done = assert.async();
visit('/');
andThen(function() {
assert.strictEqual(find('.xdsoft_datetimepicker:visible', 'body').length, 0);
});
click('.xdsoft_datetimepicker');
setTimeout(() => {
andThen(function() {
assert.strictEqual(find('.xdsoft_datetimepicker:visible', 'body').length, 1);
done();
});
}, 500);
});
My goal is to alter the component so I can rely on the click test helper to block until the jQuery element is on screen. Something like didInsertElement or the run loop waiting for a promise that I can resolve once the element is on screen would be perfect. Does anything like this exist?

You could look into creating an Asynchrony wait helper that waits for the plugin to display before continuing

Related

Vue-js event after full rendering

Vue-js I have been trying to use a simple javascript onload event that moves the page down to a particular row in a table. Those rows are separate components, each with its own id. Something like this:
mounted: function () {
this.getExcList(); // load data for exceptions from server
this.$nextTick(() => {
location.hash = "exc_"+this.excn0;
});
},
It works fine if you run it once the page is loaded, but apparently the mounted event is just too early. In this case, the data for loading (this.getExcList) only arrives then.
Is there a simple answer to this question: How do you run an onload event in Vue-js, that only happens after the render is complete?
There are so many questions online about things like this. Surely there is a standard answer? Thanks!
Update, based on comments:
Trying this
async created () { // backend to get data on exceptions
await this.getExcList(this.archiveyear); // load data for exceptions
},
mounted: function () {
this.$nextTick(() => {
location.hash = "exc_"+this.excn0;
});
},
It still doesn't jump to the location.

Ember drag-and-drop setTimeout before drag starts

I have a draggable-object from Ember drag-and-drop library (https://github.com/mharris717/ember-drag-drop) that default behaves like dragStart is performed instantly. I need to force that object, to start drag when user holds mouse button down for some time, and I thought that I can do it in dragStartAction method delivered by drag-and-drop library, but this solution don't work as expected. its still instant dragStart.
draggable-object from my hbs:
{{#draggable-object
dragHandle=".js-dragHandle"
overrideClass=classes
tagName="tbody"
content=this
dragStartAction=(action "onDragStart")
dragStartHook=(action "onDragStartHook")
dragEndHook=(action "onDragEndHook")
dragEndAction=(action "onDragEnd")
}}
onDragStart action:
#action
onDragStart(componentInstance, data) {
setTimeout(() => {
if (!this.selectedRowIds.includes(this.transaction.id)) {
this.send("selectRow", this.transaction.id);
}
this.selectCoupledVoidPayments();
this.transferTransactions.onDragStart(findComponentObject(componentInstance), this.selectedRowIds, data);
}, 500);
}
onDragStartHook action:
#action
onDragStartHook(event: Event) {
this.transferTransactions.onDragStartHook(event);
}
I was thinking that I can resolve that by using somehow custom delay helper like this, but this is prohibited in my place, and I don't even know that this will do the job.
{{#draggable-object
dragHandle=".js-dragHandle"
overrideClass=classes
tagName="tbody"
content=this
dragStartAction=(action (delay "onDragStart"))
dragStartHook=(action "onDragStartHook")
dragEndHook=(action "onDragEndHook")
dragEndAction=(action "onDragEnd")
}}
What am I doing wrong, or what is the correct way to implement delay in Ember drag-and-drop?

Webdriver.io : Wait for method

I have a problem in my automatic test scenario when I try to call my function costumtra using webdriver.io.
I want that the scenario waits until the method call finish
describe('senario', function() {
it('can click submit button', function() {
// Do something
browser.costumtra(browser.element('#submit'));
// Do something
}
});
browser.addCommand("costumtra", function(element) {
// Do something
}
any solution please ?
You can define custom commands at any point in your test suite, just make sure that the command is defined before you first use it (the before hook in your wdio.conf.js might be a good point to create them). Also to note: custom commands, like all WebdriverIO commmands, can only be called inside a test hook or it block. May be your are calling the test method before define it. change it as given below.
browser.addCommand("costumtra", function(element) {
// Do something
}
describe('senario', function() {
it('can click submit button', function() {
// Do something
browser.costumtra(browser.element('#submit'));
// Do something
}
});

Jasmine - Wait Async library to load completely before performing tests

My project contains an external library that use async XMLHttpRequest to load data. The loading time can vary between 200ms to 10000ms.
I would like Jasmine to perform the tests only when that library has finished loading.
I am a little bit confuse with the Async testing in Jasmine. I would like to have only one timeout that will wait beforeAll tests, then perform each test synchronously.
Is it possible? I have something like below, but it's not working.
describe("External library cartovista", function() {
beforeAll(function(done){
var cartovista = window.cartovista;
done();
}, 10000);
it("cartovista should be loaded", function(done) {
expect(cartovista).toBeDefined();
done();
});
it("cartovista component and data working as wanted", function(done) {
//an example of testing over the data
var data = cartovista.data[0]
expect(cartovista.afunction(data)).toBe(true);
done();
});
//etc...
});
Edit: I have to mention that I want to perform the tests with the real data.
I have found a way to do what I am trying to do. I was pretty close to a correct answer in my question.
Note that the DEFAULT_TIMEOUT_INTERVAL should be greater than the setTimeout interval
describe("External library cartovista", function() {
jasmine.DEFAULT_TIMEOUT_INTERVAL = 11000;
var cartovista;
beforeAll(function(done){
setTimeout(function() {
cartovista = window.cartovista;
done();
}, 10000);
});
it("cartovista should be loaded", function() {
expect(cartovista).toBeDefined();
});
it("cartovista component and data working as wanted", function() {
//an example of testing over the data
var data = cartovista.data[0]
expect(cartovista.afunction(data)).toBe(true);
});
//etc...
});
See Jasmine doc

jQuery children().fadeOut() then execute a single function

I have a jQuery function that looks like this:
$.get(urlCall, function (data) {
$('#divId').children().fadeOut("slow", function() {
$('#divId').append(data);
$('#divId').fadeIn("slow");
});
});
The problem is that it is calling the append and fadeIn lines once for EACH child under '#divId'. I was expecting the line
$('#divId').children().fadeOut("slow", function() {
to fade out all children and then execute the function() a single time. But since it's executing the function() once for each child, I'm appending a lot of lines that I don't want appended.
I'm sure that there must be a way to say, "fade out all children, and then do X once", but I can't seem to figure out how to do it.
Help?
you can use .promise()
$('#divId').children().fadeOut("slow").promise().done(function() {
$('#divId').append(data);
$('#divId').fadeIn("slow");
});
The .promise() method returns a dynamically generated Promise that is
resolved once all actions of a certain type bound to the collection,
queued or not, have ended.
By default, type is "fx", which means the returned Promise is resolved
when all animations of the selected elements have completed.
For the the downvoter
Demo: Fiddle
The only way to reliably do this is to make your own function that keeps track of how many animations have completed, and compares against the number of original animations. Something like:
var target = $("#divId"),
children = target.children();
$("#trigger").on("click", function () {
toggleFadeAll(children, function () {
$("#message").fadeToggle();
});
});
function toggleFadeAll(els, callback) {
var counter = 0,
len = els.length;
els.fadeToggle(function () {
if (++counter === len) {
callback.call(null);
}
});
}
DEMO: http://jsfiddle.net/jbE3C/
(this will obviously need to be adjusted based on what animating you actually want to happen)
The toggleFadeAll will call the callback provided when all fadeToggle animations have completed.
Using .promise() fails (doesn't execute the desired callback at the right point in time) when there are other animations possibly happening to the elements.
Why not just separate the fading and the appending? So it would be
$.get(urlCall, function (data) {
$('.someElement').each(function(){
$('.fadeElement').fadeIn();
});
$('.otherElement').append(data)
});

Categories

Resources