I use yepnope.js as a resource loaded. I want to execute code in my JS module only when all the dependencies for that module have been loaded. I do not want to load JS dependencies that already been loaded.
Suppose, I have dependencies D1.js and D2.js. I tried
yepnope({
load: ['D1.js', 'D2.js],
complete: function() {
//execute my code here
}
});
That works, but, resources are loaded every time, even if they were already loaded before.
If I do multiple tests like that:
yepnope([{
test: $().d1,
nope: 'D1.js'
},
{
test: $().d2,
nope: 'D2.js'
}]);
It's not clear where to put the overall completed function -- the one that runs after all the resources have been loaded.
Is it possible to do this with yepnope, or do I need to use a different component?
Thanks.
Let's say you need to conditionally load jquery.js, jquery.jgrowl.js, and jquery.powertip.js.
You'd expect the following code to work:
yepnope([{
test: typeof(window.jQuery) === 'undefined' ||
jQuery.fn.jquery.match(/^1\.[0-9]+/) < 1.7,
yep: '//cdnjs.cloudflare.com/ajax/libs/jquery/2.0.0/jquery.min.js'
},
{
test: typeof(window.jQuery) === 'undefined'
|| typeof(window.jQuery.fn.jGrowl) === 'undefined',
yep: ['//cdnjs.cloudflare.com/ajax/libs/jquery-jgrowl/1.2.12/jquery.jgrowl.min.js',
'//cdnjs.cloudflare.com/ajax/libs/jquery-jgrowl/1.2.12/jquery.jgrowl.css'],
complete: function() {
console.log('completed loading jGrowl (should fire first, or not at all)');
}
},
{
test: typeof(window.jQuery) === 'undefined'
|| typeof(window.jQuery.fn.powerTip) === 'undefined',
yep: ['//cdnjs.cloudflare.com/ajax/libs/jquery-powertip/1.1.0/jquery.powertip.js',
'//cdnjs.cloudflare.com/ajax/libs/jquery-powertip/1.1.0/jquery.powertip.min.css'],
complete: function() {
console.log('completed loading powertip');
jQuery.jGrowl("Growling!");
}
}
]);
However, if this runs on a page where jquery.powertip.js is already loaded, but jquery.jgrow.js is not, this will throw an error, due to the 'complete' callback being fired right away, instead of when all the files are done loading.
The following fiddle demonstrates this bug with yepnope 1.5.4:
http://jsfiddle.net/dergachev/HHxK2/
Note also that in the current trunk (master branch) of yepnope, this bug goes away.
It's probably related to the following tickets (which were never backported to 1.5.4):
https://github.com/SlexAxton/yepnope.js/pull/140
https://github.com/SlexAxton/yepnope.js/issues/132
https://github.com/SlexAxton/yepnope.js/issues/100
https://github.com/SlexAxton/yepnope.js/issues/96
https://github.com/SlexAxton/yepnope.js/issues/29
The callbacks are run after the corresponding scripts are executed (not just loaded). All the scripts run in order, so if you put a callback or a complete property on the last object, it'll run last.
Related
I have a jest test file that looks like this:
import Client from "socket.io-client"
describe("my awesome project", () => {
let clientSocket;
beforeAll((done) => {
clientSocket = new Client(`http://localhost:3000`);
clientSocket.on("connect", done);
});
afterAll(() => {
clientSocket.close();
});
it("should work", (done) => {
clientSocket.on("redacted", (message) => {
expect(2 + 2).toBe(56);
//expect(message === "foobar").toEqual(true);
done();
});
clientSocket.emit("redacted", "world");
});
});
This is a POC and this currently the entire implementation.
The jest.config looks like this:
export default {
// Automatically clear mock calls, instances, contexts and results before every test
clearMocks: true,
// Indicates whether the coverage information should be collected while executing the test
collectCoverage: true,
// The directory where Jest should output its coverage files
coverageDirectory: "coverage",
// Indicates which provider should be used to instrument code for coverage
coverageProvider: "v8",
// A preset that is used as a base for Jest's configuration
preset: "ts-jest",
};
Which is just the file the --intit command generated.
The core of my problem is that any expect I use that results in a failed test, no matter how trivial takes an absurd amount of time to complete. I accidentally left it running as above overnight and it eventually completed in 14 hours.
But with a passing test Jest is absolutely fine and completes rapidly.expect(2 + 2).toBe(4); for example runs perfectly. On the failed tests I see the data come back from the socket as expected in the time expected. Its only when the expect is hit that it stalls out. So I don't believe the problem is in the socket setup or some sort of communication problem.
I've tried the config based solutions I've found to no effect - eg Jest - Simple tests are slow
This is being run on my local windows machine from a terminal I'm fully starting and stopping for each test on my IDE.
OK so now I see the problem, I needed a try catch.
Can't quite believe none of the examples or docs I looked at as much as hinted this is necessary to handle something so basic.
test("should work", (done) => {
clientSocket.on("redacted", (message: string) => {
try {
expect(2 + 2).toBe(56);
//expect(message === "foobar").toEqual(true);
done();
} catch (err) {
done(err)
}
});
clientSocket.emit("redacted", "world");
});
I was writing tests for some authentication endpoints when I came across a bug like issue that I cannot seem to figure out.
This test won't pass:
it("Testing /auth/signup/lol", () => {
const test = true;
expect(test).toBe(true);
console.log("finished test?");
});
The only way I can reproduce this issue is taking all the setup and teardown code, then moving it to another file, along with the test that's troubling me (as I have done, this test copied from auth.test.js).
I've spent the morning trying to figure out the issue, the only time the test has passed is when I removed the setup code. However on notebooks.test.js and auth.test.js (excluding the last two three tests at the bottom of the auth.tests.js script) the setup codes works as intended.
What's wrong with this code?
Steps to reproduce:
Clone this repository
Switch to the develop branch
Go to the backend directory
Install all packages
Run 'npm test tests/endpoints/auth2.test.js'
I would post a small program reproducing the issue, but all attempts to do so failed.
there's a timeout in the afterEach() method because collections.users.drop() returns an undefined value (result is undefined).
At the minimum, add an else clause when testing result value so you can exit method before reaching the 10s timeout.
Maybe some additional code is required but I don't know the logic of your code and test so maybe afterEach should do more things.
Here is the working code:
afterEach(done => {
server.getTokenManager().empty()
let collections = server.getClient()?.connection.collections
if (collections === undefined) {
done()
return
}
if (collections.users !== undefined) {
collections.users.drop((err: any, result: any) => {
if (result) {
done()
} else {
done()
}
})
}
}, 10000)
The rest of the code is ok.
Preparation
Hi i am using CasperJS in combination with grunt-casper (github.com/iamchrismiller/grunt-casper) for running automated functional and regression tests in our GUI Development process for verification.
We use it like this, casper runner in gruntfile.js:
casper: {
componentTests: {
options: {
args: ['--ssl-protocol=any', '--ignore-ssl-errors=true', '--web-security=no'],
test: true,
includes: ['tests/testutils/testutils.js']
},
files: {
'tests/testruns/logfiles/<%= grunt.template.today("yyyy-mm-dd-hhMMss") %>/componenttests/concat-testresults.xml': [
'tests/functionaltests/componenttests/componentTestController.js']
}
},
so as it can be seen here we just normally run casper tests with SSL params and calling only ONE Controllerclass here instead of listing the single tests (this is one of the roots of my problem). grunt-casper delivers the object which is in charge for testing and inside every single Controllerclass the tests are included and concatenated....
...now the componentTestController.js looks like the following:
var config = require('../../../testconfiguration');
var urls = config.test_styleguide_components.urls;
var viewportSizes = config.test_styleguide_components.viewportSizes;
var testfiles = config.test_styleguide_components.testfiles;
var tempCaptureFolder = 'tests/testruns/temprun/';
var testutils = new testutils();
var x = require('casper').selectXPath;
casper.test.begin('COMPONENT TEST CONTROLLER', function(test) {
casper.start();
/* Run tests for all given URLs */
casper.each(urls, function(self, url, i) {
casper.thenOpen(url, function() {
/* Test different viewport resolutions for every URL */
casper.each(viewportSizes, function(self, actViewport, j) {
/* Reset the viewport */
casper.then(function() {
casper.viewport(actViewport[0], actViewport[1]);
});
/* Run the respective tests */
casper.then(function() {
/* Single tests for every resolution and link */
casper.each(testfiles, function(self, actTest, k) {
casper.then(function() {
require('.'+actTest);
});
});
});
});
});
});
casper.run(function() {
test.done();
});
});
Here you can see that we running a 3 level loop for testing
ALL URLs given in a JSON config file which are contained in an ARRAY of String ["url1.com","url2.com"....."urln.com"]
ALL VIEWPORT SIZES so that every URL is tested in our desired Viewport resolutions to test the correct Responsibility behaviour of the components
ALL TESTFILES, all testfiles only include a TEST STUB what means, no start, begin or something else, its all in a large Testsourrounding.
MAYBE this is already mocky and can be done in a bette way, so if this is the case i would glad if someone has proposals here, but don't forget that grunt-casper is involved as runner.
Question
So far, so good, the tool in general works fine and the construction we built works as we desired. But the problem is, because all testfiles are ran in a large single context, one failing component fails the whole suite.
In normal cases this is a behaviour i would support, but in our circumstances i do not see any proper solution than log the error / fail the single testcomponent and run on.
Example:
I run a test, which is setUp like described above and in this part:
/* Single tests for every resolution and link */
casper.each(testfiles, function(self, actTest, k) {
casper.then(function() {
require('.'+actTest);
});
});
we include 2 testfiles looking like the following:
Included testfile1.js
casper.then(function () {
casper.waitForSelector(x("//a[normalize-space(text())='Atoms']"),
function success() {
casper.test.assertExists(x("//a[normalize-space(text())='Atoms']"));
casper.click(x("//a[normalize-space(text())='Atoms']"));
},
function fail() {
casper.test.assertExists(x("//a[normalize-space(text())='Atoms']"));
});
});
Included testfile2.js
casper.then(function () {
casper.waitForSelector(x("//a[normalize-space(text())='Buttons']"),
function success() {
casper.test.assertExists(x("//a[normalize-space(text())='Buttons']"));
casper.click(x("//a[normalize-space(text())='Buttons']"));
},
function fail() {
testutils.createErrorScreenshot('#menu > li.active > ul > li:nth-child(7)', tempCaptureFolder, casper, 'BUTTONGROUPS#2-buttons-menu-does-not-exist.png');
casper.test.assertExists(x("//a[normalize-space(text())='Buttons']"));
});
});
So if the assert in testfile1.js fails, everthing failes. So how can i move on to testfile2.js, even if the first fails? Is this possible to configure? Can it be encapsulated somehow?
FYI, this did not work:
https://groups.google.com/d/msg/casperjs/3jlBIx96Tb8/RRPA9X8v6w4J
Almost similar problems
My problem is almost the same like this here:
https://stackoverflow.com/a/27755205/4353553
And this guy here has almost another approach i tried but got his problems too because multiple testsuites ran in a loop occuring problems:
groups.google.com/forum/#!topic/casperjs/VrtkdGQl3FA
MUCH THANKS IN ADVICE
Hopefully I understood what you ware asking - is there a way to suppress the failed assertion's exception throwing behavior?
The Tester's assert method actually allows for overriding the default behavior of throwing an exception on a failed assertion:
var message = "This test will always fail, but never throw an exception and fail the whole suite.";
test.assert(false, message, { doThrow: false });
Not all assert helpers have this option though and the only other solution I can think of is catching the exception:
var message = "This test will always fail, but never throw an exception and fail the whole suite.";
try {
test.assertEquals(true, false, message);
} catch (e) { /* Ignore thrown exception. */ }
Both of these approaches are far from ideal since the requirement in our cases is to not throw for all assertions.
Another short term solution that requires overriding the Tester instance's core assert method is (but is still quite hacky):
// Override the default assert method. Hopefully the test
// casper property doesn't change between running suites.
casper.test.assert =
casper.test.assertTrue = (function () {
// Save original assert.
var __assert = casper.test.assert;
return function (subject, message, context) {
casper.log('Custom assert called!', 'debug');
try {
return __assert.apply(casper.test, arguments);
}
catch (error) {
casper.test.processAssertionResult(error.result);
return false;
}
};
})();
That said, I'm currently looking for a non-intrusive solution to this "issue" (not being able to set a default value for doThrow) as well. The above is relative to Casper JS 1.1-beta3 which I'm currently using.
Is there a way (preferably Firefox or Chrome) to log all the DOM methods invoked/properties modified by a Web app?
I need this to understand some of the working of web apps whose code I don't have in non-minified version.
I understand that this won't give me the complete picture, but I am more interested in the web app's interaction with the browser for my purpose.
You can log all method calls for specific class of objects by wrapping all of its methods with a custom logging function:
var originalMethod = SomeObject.prototype.someMethod;
SomeObject.prototype.someMethod = function() {
//log this call
originalMethod.apply(this, arguments);
}
I've created a function that hooks up such wrappers to all (non-inherited) methods of given class and logs all calls to the console:
function logMethodCalls(className) {
function wrapMethod(className, methodName, prototype) {
var orgMethod = prototype[methodName];
return function() {
window.console.debug('%c'+className+'::%c'+methodName, 'color: #FBB117; font-weight: bold', 'color: #6F4E37', {
details: {
scope: this,
arguments: arguments
}
});
return orgMethod.apply(this, arguments);
};
}
if(!window[className] || typeof window[className] !== 'function') {
window.console.error('Invalid class name.');
return;
}
var prototype = window[className].prototype;
for(var i in prototype) {
if(prototype.hasOwnProperty(i)) {
if(typeof prototype[i] === "function") {
prototype[i] = wrapMethod(className, i, prototype);
}
}
}
}
I'm running it like this:
["Document", "DocumentFragment", "Element", "Event", "HTMLElement", "HTMLDocument", "Node", "NodeList", "Window"].forEach(function(i){
logMethodCalls(i);
});
You can customise the array above to track only classes that you are interested in.
The output looks like this:
To be perfectly honest there is so much output that I don't think this type of debugging may be usable. You can try extending this solution even more by observing all properties (e.g. by defining getters and setters or proxies for all objects), but this will get even more messy.
Great idea! Tracking DOM changes may be useful when trying to understand how website/app works, but also while searching for performance bottlenecks (DOM access is expensive).
I haven't found extension that does exactly what you are asking for, so I've created one. You can install DOMListener from Chrome Web Store.
DOMListener extension uses MutationObserver to catch all DOM changes and outputs friendly messages to the DevTools console. Note that I'm using console.debug() so you can easily filter these messages out:
Code is available on GitHub. If you prefer to avoid installing the extension or you want to get a similar output in Firefox, simply grab the DOMListener.js file and run it in the console.
Risking of asking a stupid question I will give it a try though.
Is it possible to display a progress indicator while RequireJs is loading dependencies?
For example:
require(['jquery'], function($) {
// Well, jQuery loaded in quite some time due to a low-speed connection
//
// Or maybe I wanted to show an overlay to prevent user of clicking on UI widgets until the load is complete
});
I don't want to start modifying the RequireJS source if there's some plugin out there which didn't show up in my Google searches.
Thanks for all your help.
It is possible to display a spinner or progress indicator, but not the bar itself. I could get status of requirejs (currently loading or idle), but not the % of loaded/needed to be loaded modules, because their dependencies are parsed upon every module load, but not at the beginning.
But, anyway, page with, at least, a simple spinner, is much better, than just blank page, while user waits.
No changes to requirejs needed! So..
Assume we have file require.conf.js with
require.config({...})
require(["app"], function () {
// main entry point to your hugde app's code
});
and it is loaded by html using
<script data-main="require.conf" type="text/javascript" src="bower_components/requirejs/require.js"></script>
This is standard requirejs scenario. Let's add the indicator to the
<div id="requirejs-loading-panel">
<div id="requirejs-loading-status"></div>
<div id="requirejs-loading-module-name"></div>
</div>
Ok, let's catch up requirejs's function called require.onResourceLoad and do all the magic needed. It will be called by requirejs upon every module load, passing the requirejs's context with dep tree and all other staff. We will use context to find out, whether requirejs is loading something or not. I did it in scheduled timer call, because onResourceLoad() is called only while loading, not when it is done loading. This code needs to be added to require.js.conf:
require.onResourceLoad = function (context, map, depMaps) {
var loadingStatusEl = document.getElementById('requirejs-loading-status'),
loadingModuleNameEl = document.getElementById('requirejs-loading-module-name');
var panel = document.getElementById('requirejs-loading-panel');
if (loadingStatusEl && loadingModuleNameEl) {
if (!context) { // we well call onResourceLoad(false) by ourselves when requirejs is not loading anything => hide the indicator and exit
panel.style.display = "none";
return;
}
panel.style.display = ""; // show indicator when any module is loaded and shedule requirejs status (loading/idle) check
clearTimeout(panel.ttimer);
panel.ttimer = setTimeout(function () {
var context = require.s.contexts._;
var inited = true;
for (name in context.registry) {
var m = context.registry[name];
if (m.inited !== true) {
inited = false;
break;
}
} // here the "inited" variable will be true, if requirejs is "idle", false if "loading"
if (inited) {
require.onResourceLoad(false); // will fire if module loads in 400ms. TODO: reset this timer for slow module loading
}
}, 400)
if (map && map.name) { // we will add one dot ('.') and a currently loaded module name to the indicator
loadingStatusEl.innerHTML = loadingStatusEl.innerHTML += '.'; //add one more dot character
loadingModuleNameEl.innerHTML = map.name + (map.url ? ' at ' + map.url : '');
}
} else {
}
};
One problem is: we cannot somehow figure out how much modules are needed to load, so we can't compute the actual % of loading progress. But, at least, we can find out, whether we're loading something or not (and event get currently loading module name) and show it to a nervous user
Since v. 2.1.19 RequireJS has onNodeCreated config property. If you assign a function to it, that function will be called each time a <script> element is appended to a document to load a module.
The function will be provided with node, config, moduleName, and url arguments. By attaching event listeners to the node, you can detect when the script has been loaded or failed to be loaded.
Now you can detect when loading process starts and stops and can use that information to notify users:
require.config({
/* ... paths, shims, etc. */
onNodeCreated: function(node, config, moduleName, url) {
console.log('module ' + moduleName + ' is about to be loaded');
node.addEventListener('load', function() {
console.log('module ' + moduleName + ' has been loaded');
});
node.addEventListener('error', function() {
console.log('module ' + moduleName + ' could not be loaded');
});
},
});
For IE < 9 you'd need additional code to attach event listeners.
Note: this only works for modules requested by RequireJS directly. Plugins (requirejs/text and such) each use their own loading mechanism and do not trigger onNodeCreated. Some trigger onXhr and onXhrComplete though, so you can handle them too:
require.config({
/* ... paths, shims, etc. */
config: {
text: {
onXhr: function(xhr, url) {
console.log('file ' + url + ' is about to be loaded');
},
onXhrComplete: function(xhr, url) {
console.log('file ' + url + ' has been loaded');
}
}
}
});
No, this isn't possible. RequrieJs loads the module by creating a new script tag in the DOM and listens to the load event. There are no update events in between start and end loading. So it's not a limitation of requireJs but the DOM.