Ember Unit testing: counting new items rendering - ember.js

I wrote a controller that holds a list, and by clicking a "get more" button, renders 5 more items of that list. I want to create some tests for that, and I want to validate that it only renders 5 more items (instead of re-rendering the entire list).
Is this even possible?

It very depends on what 're-rendering' is for you.
You can check if IDs of the old items were not changed and if their state is still valid. This was an issue that I have to solve by using Ember.ArrayProxy.
If you want to test if browser have to re-render it, you can try to count number of execution of 'init' method - https://guides.emberjs.com/v2.6.0/components/the-component-lifecycle/

Related

Apollo useQuery stuck in loading = true condition after offline mutation

16m
I am trying to complete a robust offline React, PWA using Apollo.
I have a functional component that uses useQuery to retrieve a list of items. It is using the default fetchPolicy. When this component renders, it successfully retrieves the data. If I am online or offline it works just fine.
If I am offline and I make a call to useMutation to create a new item, the list updates correctly, since I am using optimisticResponse and the update feature of mutations.
The problem happens when I navigate away from the list component, so that it is no longer rendered, then I return. Upon returning, the functional component that list all of the items is rendered again, it is stuck in the loading=true condition since I invoked the mutation. All this time the app is still offline. While in this loading state, I try to create another item while offline. The list never optimistically updates in this situation.
What do I have to do to get this to work? Is there a fundamental flaw to my basic approach to making this an offline-first app?
Here is a summary of the steps that create the problem.
Functional component executes a query and retrieves a list of items and renders them without issues.
Place the app offline.
While the list component is still rendered, invoke a mutation to create a new item while offline.
Optimistically update the UI (by updating the cache) with no issues.
Navigate away from the list component.
Navigate back to the list component (forcing a rerender of the entire list component)
The list component useQuery/loading value is stuck in true condition.
Attempt to create another item the same way as before.
The list does not optimistically update.
I cannot seem to figure this one out.

Updating model hasMany relationships in UI

I've trying to modify the contents of a hasMany relationship view some UI elements. I have two basic models, container and item. Containers have multiple items and they can have varying numbers of items. For instance:
App.Container.FIXTURES = [
{id:1,name:'Container 1',slots:[0,0]},
{id:2,name:'Container 2',slots:[0,0,0,0]},
{id:3,name:'Container 3',slots:[0,0,0]}
];
I'm using the id 0 as sort of an empty item. It shows that this container can have an item here, but it's currently empty. There are numerous different items that can go into each position.
In my app, I have a custom UI that I've created that allows a user to select a new item to fill each slot. The problem is that for some reason, it's not updating in the container model. No matter what I try, it's just updating in the view, but not on the actual model instance. I thought this would work because the properties would be automatically bound.
I've created a JSBin here displaying the problem. If you click the save button, a json object of the current state of the model will be printed to the console.
What can I do to update the actual model properties? Please keep in mind that the position matters. For instance, if I change the item in the middle position of three, only it should update; not pushed onto the end.
Thanks. Any ideas would be appreciated.
This is a modelling issue.
You have Container, each of which has many Item... except that what's actually happening is you're using the Item class as your options - this is your catalogue, if you will, and you want to put these items into "slots" which you haven't created a model for.
So, depending on what you want to do, you should probably model it like this (using better names - I chose mine for clarity of explanation):
Container hasMany Slots each of which is connected to its Item
So: Container hasMany -> Slots <- belongsTo Item
That is, you have a non-reified "join", which you're sort of calling "slots" and attaching to Container at the moment.
I say depending on what you want to do because I'm not sure if you want to have the simple case I outlined above, which is "here are a bunch of possible items you can choose to put any number of copies of into your containers" or if you want the more complicated to develop case which is "here is a bunch of items which are finite... as you add each item to a container, it disappears from the list of possibilities". To do the latter is much more complicated, but of course it's possible... this is how inventory systems work.
I hope that's answered your question...
To put it another way, you need to build yourself a Slot model, related to each of your other models, and manage the join properly. If you bind the slots properly to each dropdown then Ember will take care of hooking up the data for you.
Let me know if you need further help on how to do this.
I've modified your JSBin to comprehensively show you what I mean. Hope that helps explain it:
http://emberjs.jsbin.com/tenoqimu/5/edit

stop meteor rerender every child template inside of each block when find query changes?

i'm rendering a list of elements based on a collection on the meteor server.
the elements are rendered using an #each block which is populated from a helper method that returns a cursor which is the result of a find query. in order to sort the list based on some attribute of its data i run a new find with a different sort option.
this works fine and the list is rendered in the desired order. the problem is meteor is rerendering each element.
now i have two problems:
1) the elements can contain an embedded video that is playing. this is reset when meteor rerenders the element
2) i want to have some css transitions animate the repositioning of the elements. since meteor rerenders every element in the dom, the css transitions don't work.
i was partially able to solve problem #1 using a constant block but problem #2 remains a mystery. i could do all the sorting and filtering client side without relying on meteor but that seems clumsy.
is there any way that meteor can just reposition the elements in the dom instead of removing and readding them?
in the documentation for renderList i found this (which makes it seem like meteor could at least theoretically do what i want):
renderList is more efficient than using Meteor.render to render HTML for a list of documents. For example, if a new document is created in the database that matches the query, a new item will be rendered and inserted at the appropriate place in the DOM without re-rendering the other elements. Similarly, if a document changes position in a sorted query, the DOM nodes will simply be moved and not re-rendered.

Playframework 2 include a updatable combobox in a list (not a form)

I am using play framework 2.0 .I a page where I list all the elements that the user can edit/delete. one of the listed elements in a look up from another table. I have coded a select in the forms and that works fine.
I would like to include the combo box in the displayed list, so the user can update it right there without having to drill down into each element to update the field. Is there a way to do this? I want to listen to the change in the combobox and update the underlying model.
I tried a few iterations, but the select box seems to want a play.api.data.Field , and not the value I provide.
the parameters to the page is a pageable list like this
#(currentPage: Page[Deal], currentSortBy: String, currentOrder: String, currentFilter: String)
I don't know if I understand the issue, but I think the problem you are stating would be better solved at the client, with some ajax in it...
otherwise, you would be issuing a whole page refresh every time the user updates the items
I would expose the pageable list like a rest-json web service, and I wuld call it from javascript, binding the on-change event...
Here you have an example using select2 to do the lookup and consumign a rest web service: http://bb-jugar.rhcloud.com/assets/js/tmp/select2/demo.html

Emberjs Handlebars #each helper slow when bound to computed properties

I'm running into a performance issue when I render a list of items using the #each helper or a collection view bound to some computed properties of an Ember.ArrayController. Performance is fine with a small list of 10 - 20 items, but around 50 - 100 it starts to lag quite noticeably. Try checking off a few todos or clicking "Add Todo"
Example code is here: http://jsfiddle.net/Jonesy/ed3ZS/4/
I noticed that the childViews in the DOM get re-rendered with each change, which could very well be the intended behaviour at the moment, but I'd prefer to be able to just have a todo be removed from the DOM of unfinished todos list individually and appended to the bottom of the finished todos list, which would in theory be much less costly.
What I'm hoping to have answered is whether am I looking at a performance issue with Ember collection views, or is displaying a list populated from a computed property a bad idea, and if so, will I need to manually manage the todo model's location in the view layer as it changes from unfinished to finished and vice versa.
This is a side-effect of how {{#each}} (and CollectionView, which is what powers it) works.
Internally, CollectionView uses something called array observers. An array observer allows you to subscribe to mutations made to an array when they are done using Ember.Array's mutation methods (replace, pushObject, popObject, etc.) The API for array observers is described here.
What this means is that, if you push a new object into a collection view, it will insert render one new element in the DOM and leave the rest in place.
In the example you posted, however, the array is not being mutated--you're creating a brand new Array object every time a new item is added or removed. When the binding synchronizes, it replaces the old array with the new array. To {{#each}}, this is no different than removing all of the elements and then adding them back in.
The solution to the problem is to use a single array, instead of a computed property that returns a different array object each time it changes. You can see the Contacts app for an example of how to do this.
Obviously this is a very common pattern, and we'd like to add some kind of filtering that does the right thing by default to Ember.ArrayController down the road.