"undefined is not a function" in dependency checker - ember.js

I have a addon which used to work in Ember CLI 0.1.4 but now that I'm using 0.2.0 I think the likely improved ember-cli-dependency-checker is not letting my addon do it's magic.
The addon in question can be found here: ui-bs-popover.
My theory is the problem originates from a missing Bootstrap dependency that is excluded by design. Specifically, this plugin depends on Bootstrap (SASS or regular doesn't matter) but does not install it as part of the process. This is by design as it let's the user do this as an independent step (in whatever manner they choose). So while the dummy test app works just fine that is because the Bootstrap references are in the addon's Brocfile (just not in the index.js so that projects which include it would get same dependency met).
That said, the stacktrace I'm getting isn't very clear (to me anyway):
TypeError: undefined is not a function
at EmberCLIDependencyChecker.readBowerDependencies (/path/to/project/node_modules/ui-bs-popover/node_modules/ember-cli-dependency-checker/lib/dependency-checker.js:77:35)
at EmberCLIDependencyChecker.checkDependencies (/path/to/project/node_modules/ui-bs-popover/node_modules/ember-cli-dependency-checker/lib/dependency-checker.js:30:24)
at new EmberCLIDependencyChecker (/path/to/project/node_modules/ui-bs-popover/node_modules/ember-cli-dependency-checker/lib/dependency-checker.js:21:8)
at /path/to/project/node_modules/ember-cli/lib/models/addons-factory.js:44:19
at visit (/path/to/project/node_modules/ember-cli/lib/utilities/DAG.js:23:3)
at DAG.topsort (/path/to/project/node_modules/ember-cli/lib/utilities/DAG.js:82:7)
at AddonsFactory.initializeAddons (/path/to/project/node_modules/ember-cli/lib/models/addons-factory.js:40:9)
at Class.Addon.initializeAddons (/path/to/project/node_modules/ember-cli/lib/models/addon.js:189:36)
at setupRegistryForEachAddon (/path/to/project/node_modules/ember-cli/lib/preprocessors.js:18:10)
at Object.module.exports.setupRegistry (/path/to/project/node_modules/ember-cli/lib/preprocessors.js:46:3)

Related

ember addons test-support directory

I've some test helpers in my addon. I want to:
use these helpers for my addon's own tests.
make these helpers available to my addon's users, for testing their own codes.
In the documentation, it is said that test-support can be used to satisfy the second requirement mentioned above; but I couldn't find a way to make it work for both.
The docs say "merged with the application’s tests/",
An applications test-helpers reside in test/helpers/, any helper specified here should be registered automatically.
When sharing an addons test-helper, make sure it resides in test-support/helpers,
Once the directory get merged, the file should end up in the tests/helpers directory and be registered automatically.
As a reference one could take a look at the emberx-select addon,
A "select"-helper is shared using the same method specified in this answer.

Ember.js: Cannot read property 'isHelperInstance' of undefined

I'm deploying my app to my staging environment for the first time, but I'm running into an error...One of my routes is unable to render its template. I'm seeing this error in the console:
Uncaught TypeError: Cannot read property 'isHelperInstance' of undefined
I was not seeing this error in development.
I'm using ember-cli-rails to serve the app using Heroku.
How can I solve this issue?
I actually had this error due to improperly referencing a helper. My helper was called concatTwo() but in handlebars you have to reference it using kabob-case, which would be concat-two. We had some Handlebars referencing concatTwo which broke those pages and showed this error. Not surprisingly, refactoring it to use the kabob case version fixed the error.
Oddly enough, this didn't cause any problems on the development environment, even when running it with exactly the same data.
The cause of this error was due to referencing a component in a template that did not exist. The reason that I did not see the error in development is because I did not have the same data in my development environment as in staging. So I never saw the part of my template that would have caused the error.
Ember-2.6.3
In order to get my development environment to exhibit this behaviour I had to clear my node_modules/ and re-npm-install everything. I also cleared my bower_components and re-bower installed them too. Not sure which made the difference.
I think I agree with #vkoves about the kabob-case for your helpers. But also in addition, I think you must be wary of using dot-notation when referencing helpers or components.
We nested some of our format helpers in a folder named formatters. They look something like this from our Ember app's perspective: app/helpers/formatters/date
We were previously referencing this helper throughout our application as either: {{formatters.date ...}} or (formatters.date ...).
?After some recent changes in the Node/NPM ecosystem?, it appears that we must now refer to our nested helper using a slash-notation rather than dot-notation: {{formatters/date ...}} or (formatters/date ...)
Side Note (Dot-Notation Versus Slash-Notation)
We also just discovered that Ember-2.10 removes dot-notation for referencing components...it apparently is not in the release notes. We have to go fix that everywhere in our app (https://github.com/emberjs/ember.js/issues/14659).

Addon not working

I have an Ember Addon which I've put up at Github here:
https://github.com/lifegadget/ember-dictionary
It passes all its unit tests and in a non addon form it is working fine in one of my projects but I'd like to lift it out the project and be able to use it as an addon. Still I'm clearly missing a step in how to expose the two Ember classes. This can be seen in the dummy app which tries to create a very simple model like so:
import DS from 'ember-data';
import DictionaryModel from 'ember-dictionary';
export default DictionaryModel.extend({
foo: DS.attr('string')
});
Then when the route (tests/dummy/routes/index.js) tries to use the model I get the following error:
Error while processing route: index Cannot read property 'extend' of undefined TypeError: Cannot read property 'extend' of undefined
To me this feels like a ES6/namespacing issue but I'm not sure how to overcome it. I did try the following more explicit import statement:
import DictionaryModel from 'ember-dictionary/models/dictionary-model';
but the same error occurred. Any help would be greatly appreciated.
I have bumped into enough walls that I think I can at least partially answer my question but some questions still remain so I won't mark this answer correct with the hope that others may post a more complete answer.
The first distinction I realised I hadn't been making clear enough for myself was whether to target the Ember App's namespace or to target an independent namespace for the addon. Classes defined in the app directory of the addon will be available to any application which uses the Addon in it's own namespace. In contrast, classes in the addon directory will be namespaced to the addon's namespace.
I have seen a lot people define classes in the addon's app directory and then proxy it through to the addon directory with something like:
// addon/mixins/dictionary.js
import DictionaryMixin from 'ember-dictionary/mixins/dictionary';
export default DictionaryMixin;
Although I've seen this I am still having problems getting these external namespaced classes to work. I think there may be another step needed to add a index.js entry point for the addon and then export these classes there. In any event, I'll leave this area alone as I decided to get the internal namespaced solution working first.
My next problem in the internal namespaced solution was centered around the dummy application that gets built as part of the addon creation process. I wanted this dummy application to have a model which would use the Mixin I created in the addon and I thought I'd be able to refer to it as:
import DictionaryMixin from 'ember-dictionary/mixins/dictionary';
but this couldn't be resolved by the Dummy test application so I had to resort to:
import DictionaryMixin from '../mixins/dictionary';
Which I guess is appropriate considering that my "external namespaced solution" isn't working yet ... falling back to the internally namespaced solution was required.

ember app kit: some testing functions not defined

Building my first ember app based on ember app kit.
I wanted to test the current route after transition - and found just what I need in ember docs - currentRouteName, currentURL and currentPath helper functions.
However, if I use these functions i get a "ReferencError: currentRouteName is not defined".
I stumbled upon this pull request that I suppose has the initial implementation of the same thing - but was closed in favor of adding this functionality to ember proper... For the time being, I copied the code from this PR and it does indeed get picked up and pass my tests.
Question: how can I utilize all the functions defined in my copy of ember.js in testing?
These route helper functions are defined alongside with visit and click functions, which my tests seem to pick up without issue. Or, are my tests picking these functions up from somewhere else?
Those methods weren't added as global helpers until 1.5, so they are only available in the canary builds as of writing this.
http://emberjs.jsbin.com/wipo/2/edit

How do I tell Dojo build to ignore a 'missing' template

Our application has a number of widgets that use templates that are generated on the fly via a JSP.
In the front-end code, they are included using the dojo/text plugin. This ensures that Widget lifecycle isn't kicked off until the template has been resolved and it works just fine.
Unfortunately, when we try to perform our build, we get a 311 error:
error(311) Missing dependency. module:
app/navigation/NavigationManager; dependency:
dojo/text!/author/app/templates/NavigationManager-content.html; error:
Error: text resource
(/author/app/templates/NavigationManager-content.html/x) missing
I understand what's happening here, the build process is trying to internalize the string, but when it goes to look for it, it can't locate it and so flags it as a missing dependency.
I see a number of options here:
Somehow, tell Dojo to ignore this missing dependency - this would be fine, but I'd need to be able to be specific, so that I get alerted to any other dependencies that might be missing
Somehow, tell Dojo not to try and internalize this template - this would also be fine, since there's nothing to internalize here.
Somehow, stub out the dependency so that the dependency resolution passes, but the internalization doesn't occur.
I've seen references to the
internStringsSkipList
value, but none of the following helped:
internStringsSkipList: ['/author/pepper/templates/NavigationManager-content.html']
internStringsSkipList: ['dojo/text!/author/pepper/templates/NavigationManager-content.html']
internStringsSkipList: ['/author/pepper/templates/NavigationManager-content.html/x']
Any suggestions?
I faced exactly the same problem and after reading lots of dojo documentation and source code I came to the conclusion that it's very difficult if almost impossible to do. There is, however, a very simple and elegant workaround. But before telling you how to solve the problem firstly why there is a workaround needed in the first place (so you can adjust the solution to your own circumstances):
First issue, the resource is undiscoverable
According to the Overview section of the dojo build system Reference Guide:
[The build system] “discovers” a set of resources and then applies a synchronized, ordered set of resource-dependent transforms to those resources. (…) When a resource is discovered, it is tagged with one or more flags that help identify the role of that resource. (…) After a resource is discovered and tagged, the system assigns a set of transforms that are to be applied to that resource.
So in short, any resources generated on the fly can't be discovered by the build system because they don't reside on the file system. If they can't be discovered, then they can't be tagged and no transformation can be applied to it. In particular, resourceTags is not called for such resources and you can't put them on the exclude list of a profile layer definition (compare section Layers in Creating Builds).
BTW, as far as I understand the documentation to depsScan transform, internStringsSkipList can only be used to skip resources specified using the legacy notation (dojo.something, e.g. dojo.moduleUrl).
Second issue, the plugin resolver expects a physical file
Notation dojo/text!/some/url says to use the dojo/text.js component as a plugin. I found this note in this ticket:
Every AMD plugin should have a plugin resolver in util/build/plugins and have it registered in util/build/buildControlDefault.
If you check util/build/plugins/text.js (e.g. on Github) you'll see that the error is being thrown because the dependency (that part after dojo/text! is stored in moduleInfo) is not in the resources array:
textResource = bc.resources[moduleInfo.url];
if (!textResource){
throw new Error("text resource (" + moduleInfo.url + ") missing");
}
And this is precisely because the resource couldn't be discovered during the "discovery" phase.
The difficult solution
In the difficult solution, that might or might not work, you would need to change how the transformation depsScan works. Basically, when depsScan encounters dojo/text!/some/url it calls the plugin resolver to check if the dependency exists. From the depsScan documentation:
Once all dependencies are found, the transform ensures all dependencies exist in the discovered modules. Missing dependencies result in an error being logged to the console and the build report.
That might be possible by redefining transformJobs to contain a custom transform for depsScan. See util/build/buildControlDefault.js (on Github) and this forum post for more insights.
The simple workaround
Just create your own plugin to load the resource. Your own plugin won't have the plugin resolver registered (see the second issue above) and all you'll get when compiling is the dreaded
warn(224) A plugin dependency was encountered but there was no build-time plugin resolver.
This is my example of such plugin that loads a JSON resource dynamically:
define(["dojo/text", "dojo/_base/lang", "dojo/json"],
function(text,lang,json){
return lang.delegate(text, {
load: function(id, require, load){
text.load(id, require, function(data){
load(json.parse(data));
});
}
});
});
It reuses dojo/text adding its custom load function. This is an adaptation of another example posted on this dojo-toolkit forum post. You can see their code on JSFiddle.
In my project I use the plugin like this:
define(["./json!/path/to/an/json"],
function(values){
return values;
});
Your plugin can just return the loaded template without parsing it as JSON, and as long as you don't specify your custom plugin resolver (which would expect the file to exist physically on disk) the project will compile fine.
This wasn't your issue, but the most common solution to those facing the error(311) problem is going to be this:
Don't start template paths with a slash.
Bad:
"dojo/text!/app/template/widget.html"
Good:
"dojo/text!app/template/widget.html"
Your template path isn't a normal, plain-ol' URL. It's still part of the Dojo build, so you use Dojo build pathing to get to the template.