Sencha Touch [APPNAME].app is undefined only when testing with Jasmine - testing

I'm trying to set up some test cases for a view using the Jasmine 2.3.4 assertion library for my Sencha Touch 2.4 app. Things seem great (I see the view rendered to a div) except the browser does not know what MyApp.app is. I have this line at my onContainerInitialize function from my view/container code:
var controller = MyApp.app.getController('loginController');
which gives this Jasmine error:
TypeError: Cannot read property 'getController' of undefined
At the time the Jasmine tests are called, from my console I do have a MyApp global object with the following structure (attached). If you expand app you will see the class name of the controller listed in an array under _controllers. The line that causes this error in my spec file is:
var myView = new MyApp.view.someViewName({ renderTo: 'test' });
I modeled my setup after a few tutorials, one of which is Sencha's https://docs.sencha.com/extjs/4.2.5/#!/guide/testing
(wish there was one for a recent version of Touch). I think my problem may be related to this note midway down that page:
Note: this Application definition is not a copy and paste of your
regular Application definition in your app.js. This version will only
include the controllers, stores, models, etc and when launch is called
it will invoke the Jasmine tests.
It may be related, but I also couldn't follow their:
ctrl = newMyApp.controller.MyController();
where I would get this error:
TypeError: app.getRouter is not a function at Ext.define.applyRoutes (http://localhost:8080/touch/sencha-t...ug.js:45800:26)
Instead, I had to add in this argument like this:
var ctrl = new Kaacoo.controller.loginController({ application : app });
Additionally, my launch file is set up like this:
Ext.require('Ext.app.Application');
Ext.Loader.setConfig({
enabled: true,
disableCaching: true
});
Ext.Loader.setPath('MyApp', '../../app');
// this file is a couple levels deep from the root of my project
Ext.application({
name : 'MyApp',
extend: 'MyApp.Application',
autoCreateViewport: true,
controllers: [
'loginController'
],
requires : [
],
launch: function() {
// Jasmine is bootstrapped with boot.js referenced in the html runner, so nothing here. My test specs are being called after this launch function is executed.
}
});
The order I have listed my resources in my html runner are: Jasmine Library with boot.js> Touch All Debug Library > Project Source Files > Spec Files > Launch file
Building and simulating the app is fine, so why can't I also have access to MyApp.app.getController('loginController') as well in my test environment?
Thanks!

Related

Vue.js including non-npm JavaScript library

I'm a total beginner with Vue.js and struggling to find the answer to what I feel is a fairly basic need.
I have a JavaScript library that cannot be installed locally and must be imported via script tag in the index.html file in the old-fashioned way:
<script src="https://foo.bar/scriptyscripts.js"></script>
This library has a bunch of methods in it that I need to use in various spots throughout my app, so it's not going to be a problem to load it globally. The issue I'm facing is that it's loading fine, but the methods are not being recognised in components.
I can use the methods and whatnot if I put them all in a script tag in the index.html however doing that rather defeats the whole point of having components.
Can anyone help me with the step that I'm missing to register all of the methods in this loaded js file so my components don't get mad?
Specifically, the script contains require.js and a collection of other things including JQuery.
Including the library makes the method 'require' available, which is used to load other modules on demand - the example being "js/qlik" in the below snippet. "js/qlik" loads JQuery and a stack of stuff associated with "qlik".
//async login method here. not relevant to this problem
login().then(() => {
require.config({
baseUrl:
(config.isSecure ? "https://" : "http://") +
config.host +
(config.port ? ":" + config.port : "") +
config.prefix +
"resources",
webIntegrationId: config.webIntegrationId,
});
//Load js/qlik after authentication is successful
require(["js/qlik"], function (qlik) {
qlik.on("error", function (error) {
$("#popupText").append(error.message + "<br>");
$("#popup").fadeIn(1000);
});
$("#closePopup").click(function () {
$("#popup").hide();
});
var app = qlik.openApp("caa866be-c8e1-44c8-b67b-dac9d24421fa", config);
});
});
The problem I have is that if I load this library in the index.html file and then try to execute the methods in the snippet above in any component, it does not know that the methods are available.
I see:
'Module not found: Error: Can't resolve 'js/qlik'
66:11 error '$' is not defined
which indicates that the components are unaware of the methods because they're not registered like they would be if I were importing a packaged afterinstalling it locally via NPM
i.e. Your original js code: function abc(){// sth...}
What you need: window.abc = ()=>{// sth...}
Even if you want it in Vue dom.
You should add vue.prototype.abc = ()=>{//sth...}

Multiple Aurelia Instances - Aurelia Webpack Plugin - aureliaApp option - "module not found"

I am composing my web app as a number of Aurelia "feature" apps - although I'm not using Aurelia features as such. Consequently in my html markup I have two entry points pointing to different apps:
<!-- Top Navigation Bar -->
<div aurelia-app="topnav"></div>
<!-- Main App-->
<div aurelia-app="main"></div>
I am using webpack and everything works perfectly using the single "main" app. Webpack generates a JS file "main.bundle.js" which I include in the src tag.
Things are not so straightforward when I added the "topnav" app. In webpack I tell the plugin to use a different aureliaApp name:
new AureliaPlugin({ aureliaApp: "topnav"}),
and, as you can see my HTML entrypoint also calls "topnav". Webpack generates a JS file "topnav.bundle.js" which I also include. I have a file called "topnav.ts" which contains the aurelia Cionfigure function which ends:
aurelia.start().then(() => aurelia.setRoot(PLATFORM.moduleName("nav")));
And a pair of files "nav.ts", "nav.html" which constitute my viewmodel and view.
When I run the app aurelia loads and the "nav" module code executes. But I then get an error - see below.
The module which it reports that it cannot find is the one entered into the HTML markup.
Should this work? Have I missed something?
I should add, everything seems to work. I can create and update properties in the viewmodel and these are bound to the view. It's just that this error is thrown.
You are doing nothing wrong, just unsupported scenario. Per official doc-wiki: https://github.com/aurelia/webpack-plugin/wiki/AureliaPlugin-options#aureliaapp
You can have only 1 auto entry module with aureliaApp configuration. To solve this, you just need to add PLATFORM.moduleName('topnav') to your main.ts (and put it on root level)
Another way to do is to bootstrap manually:
// in your index.ts
import { bootstrap } from 'aurelia-bootstrapper';
// bootstrap top nav application, with one instance of Aurelia
bootstrap(aurelia => {
// do your configuration
aurelia
.start()
.then(() => aurelia.setRoot(
PLATFORM.moduleName('topnav'),
document.querySelector('#topnav')
);
});
// bootstrap main application, with another instance of Aurelia
bootstrap(aurelia => {
// aurelia.use.standardConfiguration();
// ...
aurelia
.start()
.then(() => aurelia.setRoot(
PLATFORM.moduleName('app'),
document.querySelector('app')
)
});

requirejs loading file from different path

I've a webpage , where I've included the requirejs via script tag like -
<script data-main="/media/course-book-app/courses.require.main.js" src="/media/common/vendor/requirejs/require.js"></script>
On Safari browser, I'm getting error like -
What is causing this issue?
This issue is very frequent on Safari but on chrome it is less frequent.
Testing URL
From https://requirejs.org/docs/errors.html#scripterror (which is linked right there in the error). Follow the instructions and look at the script that caused the error
This occurs when the script.onerror function is triggered in a
browser. This usually means there is a JavaScript syntax error or
other execution problem running the script. To fix it, examine the
script that generated the error in a script debugger.
This error may not show up in IE, just other browsers, and instead, in
IE you may see the No define call for ... error when you see "Script
error". This is due to IE's quirks in detecting script errors.
Here is the way to use requirejs correctly. This ensures the configuration gets loaded before loading any module -
define('requireconfig', function(){
require.config({
paths: {
"jquery": "/common/vendor/jquery/jquery-1.9.1.min",
"backbone": "/common/vendor/backbone/backbone.min-1.1.2",
"underscore": mediaPath + "/common/vendor/underscore/underscore.min-1.7.0"
},
shim: {
backbone : {
deps: ["jquery","underscore"],
exports: "Backbone"
},
}
});
});
define('main', ['requireconfig'], function () {
'use strict';
});
// loading main module which loads the requirejs configuration
requirejs(['main'],()=>{
requirejs(['jquery'], ($)=>{//jquery loaded});
}, ()=>{//error loading module})

ArcGIS Api (Esri) triggering multipleDefine error

I have this weird issue while using ArcGIS API for JavaScript v4.4 in my code. I am trying to build an Excel Web Add-in in which I would like to load an ArcGIS map but when I load ArcGIS I get a multipleDefine error.
ArcGIS is getting bundled with Dojo which is used as the loader for all the ArcGIS/esri packages. I have no other choices to load my own custom JS bundles with Dojo because of the way ArcGIS has built their API. So I can't decide to not use Dojo and thus not getting the multipleDefine error.
I load my own JS files like this:
<script src="https://appsforoffice.microsoft.com/lib/1/hosted/office.js" type="text/javascript"></script>
<script>
var dojoConfig = {
parseOnLoad: false,
async: false,
// we make aliases for our js file
aliases:  [
['index',  './Bundles/index.js'],
],
};
</script>
<script src="https://js.arcgis.com/4.4/init.js"></script>
<script>
require(['index'], function (index) {
//...do something
});
</script>
When I restart the page I get a multipleDefine error once in every two/three trials. After a lot of investigation I understood that the error lies with the Office.js API but I had a hard time to find a good solution.
After a while I found the cause of the problem; we cannot start office-js and Dojo together because they both want to add scripts in the head tag of our page and somehow they end up in conflict with one another, thus we get the dreaded multipleDefined Dojo error and some of our files do not get loaded.
Once this cause was identified I decided to solve it by making sure Dojo, Argis and my custom js files got loaded once Office and dependencies were fully loaded.
I implemented it like this in my js code:
// This Dojo config variable has to be defined before Dojo is loaded in our scripts
var dojoConfig = {
// we make aliases for our custom js file
aliases: [
['index', './Bundles/index.js'],
],
// We require our dependencies (our own code bundles) with Dojo.
// Notice that it is mandatory to bundle our js files
// as AMD Modules for Dojo to be able to load them as dependencies.
deps: ['index'],
};
// Once office has fully initialized we can add our arcgis file and let
// him load our own required javascript files.
// We cannot start Office-js and Dojo/Arcgis together because they both
// want to add scripts in the head tag of the HTML page and
// somehow they end up in conflict, thus we get the dreaded
// multipleDefined Dojo error and some of our files
// do not get loaded.
Office.initialize = function (reason) {
// we manually add the Arcgis script to the header of our page
// once we are sure Office and dependencies has fully loaded.
var tag = document.createElement('script');
tag.src = 'https://js.arcgis.com/4.4/init.js';
document.getElementsByTagName('head')[0].appendChild(tag);
};
Once this was added the code started working like a charm.

intern.js How to test legacy non modular code

I'm using intern.js as a test framework to test dojo modules and it works well.
Now I have to test some non modular legacy code but I can't.
This is an example of a simple file to test:
var Component = function() {
this.itWorks = function() {
return true;
}
};
And this is the test
define([
'intern!object',
'intern/chai!assert',
'intern/order!controls/component',
], function (registerSuite, assert) {
registerSuite({
name: 'test legacy code',
'simple test': function () {
console.log(Component);
}
});
});
The test fails sayng that "Component is not defined".
I've notice that it works only if I write
window.Component = Component
At the bottom of file to test.
I can't modify all the file to test, is it possible to test the file in a different way?
This should work fine. One possible issue is where you're loading component from. The 'controls/component' dependency in 'intern/order!controls/component' is, barring any special loader config, relative to the file doing the loading. That means that if the project is setup like this:
project/
controls/
component.js
tests/
intern.js
componentTest.js
and component is being loaded from componentTest.js, then the dependency should be 'intern/order!../controls/component.js'. (It will actually work without the '../' in this case since controls is a top level directory in the project.)
Another potential issue is that a non-AMD identifier should use the .js suffix. This tells the loader that the thing being loaded is a generic script rather than an AMD module.
Also note that the order plugin is only needed to load multiple legacy files in a specific order. If order doesn't matter, or you're just loading one script, you can just use the script itself '../controls/component.js' as the dependency.
<"/"https://stackoverflow.com/tags" term="legacy" /">
<"/!-- begin snippet: js hide: false console: true babel: false --"/">
"var Component" = function() {
"this.itWorks" = function() {
return=true;
}
};
<"/"!-- end snippet --"/">