I use YUI 3 as my main Javascript library and CasperJS for testing.
In my application I load CSS dynamically. I utilize Y.Get.css like this:
Y.Get.css(
'#my_cssFile#',
{
attributes : {
id : "#css_ID#"
},
async : true,
onEnd : function () {
myCallbackFunction();
}
}
);
When I run tests with CasperJS the myCallbackFunction() is never called.
I read that some browsers have not implemented the loadEvent on link elements. CasperJs however, use a Webkit core. I suspect that something else is causing this.
I also tried using the pollInterval attribute, but with no result.
Is there a way to call a callback after loading CSS with casperJS?
Related
I have mainly worked with cypress previously for e2e automated testing, I have now started working on webdriverIO. So for a cypress command such as
cy.get("[data-testid='nav-bar']").contains("Search Box").click();
What would be the equivalent for this in webdriverIO? I have tried the following approach in a PageObject Model.
class HomePage extends Page {
get navBar() {
return browser.$("[data-testid='nav-bar']");
}
openSearchBox() {
this.navBar().click('//*[text="Search Box"]');
}
}
However, this approach does not seem to work, any help on this would be appreciated.
Leaving Page Objects asside for now, you'd type this in WebdriverIO:
const bar = $('[data-testid='nav-bar']');
expect(bar.getText()).toInclude('Search Box');
bar.click();
You can use chai for the assertion instead of Jest Matchers:
const expectChai = require('chai').expect;
// ...
expectChai(bar.getText()).to.have.string('Search Box');
// ...
The exact analog to
cy.get("[data-testid='nav-bar']").contains("Search Box").click();
can be achieved with xpath selector
$("[data-testid='nav-bar']").$("./*[descendant-or-self::*[contains(text(), 'Search Box')]]").click();
It looks a bit ugly though, consider adding a custom command that would mimic Cypress's contains:
// put this to `before` hook in your wdio.conf.js
browser.addCommand('cyContains', function(text) {
this.waitForExist()
return this.$(`./*[descendant-or-self::*[contains(text(), '${text}')]]`)
}, true)
$("[data-testid='nav-bar']").cyContains("Search Box").click();
P.S.
Check out the selector in the browser console right on this page, paste in the browser console
$x("//span[descendant-or-self::*[contains(text(), 'Search Box')]]")
I have some "classic" tiles on a Plone 4.3.6 site, which contain a richtext field and two RelationChoice fields using plone.formwidget.contenttree widgets.
I have installed plone.app.widgets 1.8.0 (along with p.a.contenttypes), and I can't get the new TinyMCE and the new relateditems pattern widget to work properly. If I load the tile view URL directly (at the ##edit-tile/.... URL), the widgets actually show up and work properly. But in the iframe/overlay, they don't.
The prep-overlay looks like this:
jQuery('.tile-editable').each(function () {
jQuery(this).find('a.tile-edit-link, a.tile-delete-link').
prepOverlay({
subtype: 'iframe',
config: {
onLoad: function (e) {
jQuery('body').addClass('noscroll');
return true;
},
onClose: function() {
jQuery('body').removeClass('noscroll');
location.reload();
}
}
});
});
The iframe loads ++resource++plone.app.widgets.js in the header, and the fields are given the pat-relateditems and pat-tinymce classes as expected. But the init method inside the relateditems pattern is never called. I suppose the iframe DOM is not parsed for patterns, but I don't know where to look for the cause of this.
FWIW, there is an error in the console:
Uncaught Error: Mismatched anonymous define() module: function (){return eb}
http://requirejs.org/docs/errors.html#mismatch
in plone.app.widgets.js:166, but I don't know where that's coming from, or if it matters.
Are there any tricks to getting mockup widgets to work in an ifram overlay?
To reinitialise all patterns you can do:
var registry = require("pat-registry");
registry.scan(SELECTOR); // document or iframe or wherever you want to rescan all patterns.
IMHO you could do this on the onLoad method.
The default Accounts-UI widget takes a while to load. I want to check on the client when it is ready, so that I can perform some DOM manipulations on it afterwards. I am currently using a timer like so:
Template.sign_in_modal.onRendered(function (){
Tracker.afterFlush(function () {
Meteor.setTimeout(function () {
$('a#login-sign-in-link').click();
$('a#login-name-link').click();
$('a.login-close-text').remove();
}, 100);
});
});
The above hack works locally (probably because it loads faster) but not when I push to saturnapi.com. I just want it to be expanded by default as shown below. Is there a way to ensure the UI widget is fully loaded via a template helper or otherwise make it expanded by default?
I would suggest checking when the <a id="login-sigin-in-link"></a> is added to the DOM. This could be verified by checking $('a#login-sign-in-link').length. If the element is on the DOM do your manipulation.
However if it is not just check again in a few milliseconds. I would suggest using setInterval().
See below for the complete solution:
Template.sign_in_modal.onRendered(function (){
var setIntervalId = Meteor.setInterval(function() {
if($('a#login-sign-in-link').length) {
$('a#login-sign-in-link').click();
$('a.login-close-text').remove();
Meteor.clearInterval(setIntervalId);
}
}, 100);
});
Template.sign_in_modal.onDestroyed(function() {
$('.modal-backdrop.fade.in').remove();
});
Some may think that using loginButtons.onRendered(function(){}); is a good way to verify if the element has been added to the DOM, but it is not. If you try to do the same DOM manipulation in onRendered, it will throw an afterFlush error. The onRendered function has been extremely misleading.
I need to execute a jQuery function after a page loaded. The docs told me that it would be possible to hook into the 'PageLoaded' observer.
So I tried it like shown there. I put this function
Behaviour.register({
'#Form_ItemEditForm' : {
initialize : function() {
this.observeMethod('PageLoaded', this.pageLoaded);
this.observeMethod('BeforeSave', this.beforeSave);
this.pageLoaded(); // call pageload initially too.
},
pageLoaded : function() {
alert("You loaded a page");
},
beforeSave: function() {
alert("You clicked save");
}
}
});
into my cms.js which get's loaded in the backend. I tried it inside and outside (function($) { .. code ..}(jQuery)); and also inside the doucment.ready function inside the first function.
I always receive the same error in my console Uncaught ReferenceError: Behaviour is not defined.
Where is my mystake?
I believe you may have been looking at docs for 2.4, not 3.x
Version 3 and up are built using jQuery.entwine, where this from memory is old Prototype plugin stuff from 2.4, meaning of course that Behaviour is not defined, just as the error says.
The docs have recently been updated, so perhaps visit again, you might learn something new & much more helpful :)
I am currently using iron-router and this is my very first attempt to try out the Meteor platform. I has been running into issues where most of the jquery libraries failed to initialized properly because the of the way Meteor renders html, $(document).ready() fires before any templates are rendered. I am wondering is there any callbacks from Meteor/iron-router that allows me to replace the jQuery's dom ready?
Also, how should I (easily and properly) handle the live update of the dom elements if some of them are customized by jQuery/javascript?
This is what i am currently doing, i feel like it is very hackish and probably would run into issues if the elements got updated after the initialization.
var jsInitalized = false;
Router.map(function () {
this.route('', {
path: '/',
layoutTemplate: 'default',
after: function(){
if(!jsInitalized){
setTimeout(function(){
$(document).ready( function() { $$$(); });
}, 0);
jsInitalized = true;
}
}
});
}
With Meteor you generally want to think about when a template is ready, not when the dom is ready.
For example, let's say you want to use the jQuery DataTables plugin to add sorting to a table element that's created by a template. You would listen to the template's rendered event and bind the plugin to the dom:
HTML:
<template name="data_table">
<table class="table table-striped" id="tblData">
</table>
</template>
JavaScript:
Template.data_table.rendered = function () {
$('#tblData').dataTable();
};
Now anytime the template is re-rendered (for example, if the data changes), your handler will be called and you can bind the jQuery plugin to the dom again.
This is the general approach. For a complete example (that includes populating the table with rows) see this answer.
Try making a separate .js file, call it rendered.js if you'd like. and then;
Template.layout.rendered = function ()
{
$(document).ready(function(){console.log('ready')});
}
I use template layout, but you can do Template.default.rendered. I hope that helps.
Also take a look at this part of documentation, especially the Template.events; http://docs.meteor.com/#templates_api
I use Meteor v0.8.0 with Iron Router (under Windows 7) and here is how I handle 'DOM ready':
When I want to modify the DOM after a specific template has been rendered:
I use Template.myTemplateName.rendered on the client side :
Template.blog.rendered = function()
{
$('#addPost').click(function()
{
...
});
}
When I want to modify the DOM after any new path has been rendered:
I use Router.onAfterAction, but there seems to be a trick:
Router.onAfterAction(function()
{
setTimeout(function()
{
$('.clickable').click(function()
{
...
});
}, 0);
});
Notice the setTimeout(..., 0), it doesn't work for me otherwise (DOM empty).
Notice that you can use onAfterAction on specific path, but most of the time I think it is redundant with the Template.myTemplateName.rendered method above.
What seems to be missing:
A way to modify the DOM after any template has been rendered.