Fetching Ember property in test returns undefined - testing

I'm brand new to Ember and I'm using Konacha to test my app. I'm having trouble using the data store in my tests. The following code attempts to check if the itemText property of an Item model is equal to the displayed text in the DOM:
it "should display the item text", ->
item = undefined
Ember.run ->
item = store.find('item', 1) # store is defined in the spec helper
content = item.get('itemText')
console.log(item) # Logs the correct item
console.log(content) # Logs undefined
$('.list-item:eq(0)').text().should.equal content # Fails since content is undefined
Clearly, the content = item.get('itemText') is not doing what I'm expecting it to. However, running the same code line by line in the console gives me back the property I want, so I'm not sure where I'm going wrong. I have a feeling I may be testing this in entirely the wrong way, so any feedback is appreciated.

I think your console logs is ran before the the model is fetched. What you need is a promise, have a look.
it "should display the item text", ->
item = undefined
Ember.run ->
item = store.find('item', 1).then (item) ->
content = item.get('itemText')
$('.list-item:eq(0)').text().should.equal content

Related

Angular Bootstrap directive not working in ng-repeat

Based on a jsfiddle I made a directive, which shows some information in a Bootstrap Popover, when hovering over a Bootstrap badge or clicking into it. It's working fine, as long it's "standalone"
I made a plunker to demonstrate
(need to add code here)
The button and the first to badges in the wells are doing fine.
The badges with dynamically generated ids in the ng-repeat are not doing anything at all.
With the badges with fixed ids, only the first one works (as this is initialized 2 times), which makes sense.
What I do not understand is, in the console log you can see, all the badges in the ng-repeat are found and set up.
Don't know, where to look anymore. Any ideas?
I would suggest that you try to rely on the angular-ui bootstrap library to accomplish the functionality that you want. But based on your reliance on using the id attribute and your desire to use dynamically generated ids I figured that your problem was in the way that you get the element with the popover attribute. You don't need to do a $("#" + elemId) to get the element for the popover, you already have a reference to the element as one of the parameters in your link function.
Right now you have:
testApp.directive "popoverClickNHover", ->
restrict: "A"
link: (scope, element, attrs) ->
asPopover = undefined
console.log "popoverClickNHover"
asPopover = (elemId) ->
clickToggle = undefined
enterShow = undefined
exitHide = undefined
popoverTriggerElem = undefined
console.log "asPopover: " + elemId
popoverTriggerElem = $("#" + elemId)
console.log popoverTriggerElem
popoverTriggerElem.data "state", "hover"
...
return
asPopover attrs["id"]
But you can just use the element that the link function gives you and it will work:
testApp.directive "popoverClickNHover", ->
restrict: "A"
link: (scope, element, attrs) ->
asPopover = undefined
console.log "popoverClickNHover"
asPopover = () ->
clickToggle = undefined
enterShow = undefined
exitHide = undefined
popoverTriggerElem = element /* just use the element, no need to do $("#"+elemId) */
console.log popoverTriggerElem
popoverTriggerElem.data "state", "hover"
...
return
asPopover
Here's an example using the element from the link function: http://plnkr.co/edit/jA6zc0JQKiQaoQNo7BaH?p=preview
And here's a different example using angular-ui/bootstrap:
http://plnkr.co/edit/jpRh0fJfiFnsOavpW55s?p=preview

AngularJS: Take a single item from an array and add to scope

I have a ctrl that pulls a json array from an API. In my code I have an ng-repeat that loops through results.
This is for a PhoneGap mobile app and I'd like to take a single element from the array so that I can use it for the page title.
So... I'm wanting to use 'tool_type' outside of my ng-repeat.
Thanks in advance - I'm just not sure where to start on this one.
Example json data
[{ "entry_id":"241",
"title":"70041",
"url_title":"event-70041",
"status":"open",
"images_url":"http://DOMAIN.com/uploads/event_images/241/70041__small.jpg",
"application_details":"Cobalt tool bits are designed for machining work hardening alloys and other tough materials. They have increased water resistance and tool life. This improves performance and retention of the cutting edge.",
"product_sku":"70041",
"tool_type": "Toolbits",
"sort_group": "HSCo Toolbits",
"material":"HSCo8",
"pack_details":"Need Checking",
"discount_category":"102",
"finish":"P0 Bright Finish",
"series_description":"HSS CO FLAT TOOLBIT DIN4964"},
..... MORE .....
Ctrl to call API
// Factory to get products by category
app.factory("api_get_channel_entries_products", function ($resource) {
var catID = $.url().attr('relative').replace(/\D/g,'');
return $resource(
"http://DOMAIN.com/feeds/app_productlist/:cat_id",
{
cat_id: catID
}
);
});
// Get the list from the factory and put data into $scope.categories so it can be repeated
function productList ($scope, api_get_channel_entries_products, $compile) {
$scope.products_list = [];
// Get the current URL and then regex out everything except numbers - ie the entry id
$.url().attr('anchor').replace(/\D/g,'');
$scope.products_list = api_get_channel_entries_products.query();
}
Angular works as following:
Forgiving: expression evaluation is forgiving to undefined and null, unlike in JavaScript, >where trying to evaluate undefined properties can generate ReferenceError or TypeError.
http://code.angularjs.org/1.2.9/docs/guide/expression
so you only need to write:
<title>{{products_list[0].tool_type}}</title>
if there is a zero element the title will be the tool_type, if not, there is no title.
Assuming you want to select a random object from the list to use something like this should work:
$scope.product-tool_type = products_list[Math.floor(Math.random()*products_list.length)].tool_type
Then to display the result just use
<h1>{{product-tool_type}}</h1>
Or alternatively:
<h1>{{products_list[Math.floor(Math.random()*products_list.length)].tool_type}}</h1>

Sencha touch List clean data

I have following code.
var list = this.getNavigation();
if (list.itemsCount > 0) {
list.removeAll(true, true);
}
list.setData(filtered);
List = xtype: list.
So idea is next i have menu and some times i need to rebuild it. as you see i am not using store because i need to filter array and set it.
When i call removeAll i got error
Uncaught TypeError: Cannot call method 'getScroller' of undefined
And i cant find method to cleanup it...
I rewrote my menu to use store and instead of setData on list i am setting data on store and it works as expected
Another option would be calling removeAll with destroy set to false like so:
var list = this.getNavigation();
if (list.itemsCount > 0) { list.removeAll(false); }
list.setData(filtered);
The list DOM items get deleted anyways by some sort of auto-cleanup.

Backbone.js Collection.models not working

I have a Rails project with Backbone.js and HAML as client side templating language.
in file app/assets/views/meeting.coffee:
class window.MeetingIndex extends Backbone.View
template: JST['meeting/index']
render: ->
#collection.fetch()
#$el.html(#template(collection: #collection))
this
in file app/assets/javascripts/templates/meeting/index.hamlc
- console.log(#collection.length) # prints 0 in console
- console.log(#collection.models) # prints [] in console
- console.log(#collection.at(0)) # prints undefined in console
- window.x = #collection
if I go to the browser console I get:
x.length # returns 2
x.models # returns [Meeting, Meeting]
x.at(0) # returns Meeting object
If I can access #collection variable in .hamlc file, because I am assigning it to window.x. Why can't I access the #collection items from the .hamlc file?
I need something like
- for model in #collection.models
%p= model.get('landlord_id')
%p= model.get('tenant_id')
%p= model.get('at')
to work
The Collection#fetch method is asynchronous (i.e. it is an AJAX call behind the curtains) so #collection.fetch() hasn't gotten anything back from the server when you try to use it in your view. However:
The options hash takes success and error callbacks which will be passed (collection, response) as arguments. When the model data returns from the server, the collection will reset.
So you can use the callbacks:
render: ->
#collection.fetch(
success: (collection, response) =>
#$el.html(#template(collection: #collection))
#
Or you can bind the view's render to the collection's reset event:
class window.MeetingIndex extends Backbone.View
template: JST['meeting/index']
initialize: ->
#collection.on('reset', #render)
#collection.fetch()
render: =>
#$el.html(#template(collection: #collection))
#
Then the fetch call in the view's initialize would indirectly trigger the proper render call when it gets something back from the server. This approach works best if your template knows what to do with an empty collection, perhaps it could detect an empty collection and display a "loading" message or just say "nothing's here yet".

For loop in coffeescript

I am working on rails3.2 and using coffeescript
In my coffeescript i have a for loop and for each , i am executing a API call to fetch results and appending the results to the respective dom
like
for ajaxLink in _ajaxRenderLinks
_template = $(ajaxLink).attr('data-link-template')
apiURL = $(ajaxLink).attr('data-link-url')
console.log($(ajaxLink))
Myapp.API.execute(apiURL, 'get', {}, (data) ->
console.log($(ajaxLink))
if data isnt "" or data isnt undefined
console.log($(ajaxLink))
$(ajaxLink).empty()
$(ajaxLink).append($(HandlebarsTemplates[Myapp.TemplateRoutes.path(_template)](data))))
In the above code, i have two links (one is a link and another is a ul link)
ajaxRenderLinks has these a and ul which has its template to render and the url to fetch the results.
The first console.log prints the first link a and then runs the API call for it and then runs the APi call for it
and then it prints the second link ul and runs the API CALl for it . And finally it tries to append the last result with the second link and not doing the appending for each link, since it ajaxLink inside if data isnt "" or data isnt undefined prints only the second link and not prints the first link and then second link
How to resolve this
Looks like a classic "variable closure in a loop" situation. Because the execute function is asynchronous, it references ajaxLink, which changes as the loop loops. So when execute's callback is invoked, ajaxLink might be something else than what it was when execute itself was invoked.
Try this
for ajaxLink in _ajaxRenderLinks
do (ajaxLink) -> # wrap in an immediately-invoked function
ajaxLink = $(ajaxLink) # save this rather than calling $(...) again and again
_template = ajaxLink.attr('data-link-template')
apiURL = ajaxLink.attr('data-link-url')
Myapp.API.execute(apiURL, 'get', {}, (data) ->
if data? and data isnt ""
ajaxLink.empty().append($(HandlebarsTemplates[Myapp.TemplateRoutes.path(_template)](data))))