Unit testing aurelia view - jasmine

I'm new to Aurelia and was wondering if there was a way to unit test the Aurelia views with it's custom bindings? I tried to load the Aurelia html view file into an html fixture using jasmine-jquery, but for some reason I could never get any of the html DOM elements using their id.
The functionality I am trying to unit test is when I mouseover an icon, it should increase the size of the icon and change it's background color.
View
<template>
<div>
<span repeat.for="[automobile] of automobilesArray">
<object id.bind="automobile.Id" type="image/svg+xml" style='background-color: white;' data.bind="'./images/' + automobile.Id +'.svg'" class="auto-icon img-circle" width="50" mouseover.delegate="mover($event)" mouseout.delegate="mout($event)">
</object>
</span>
</div>
View Model
mover(event: Event) {
document.getElementById(event.srcElement.id).style.backgroundColor = "yellow";
document.getElementById(event.srcElement.id).width = "60px";
}
mout(event: Event) {
document.getElementById(event.srcElement.id).style.backgroundColor = "white";
document.getElementById(event.srcElement.id).width = "60px";
}
I'd like to write something like this in my test file to test this. What am I doing wrong?
Test file
it("vehicle icons should grow in size on mouseover", => () {
jasmine.getFixtures().fixturesPath = 'base/';
loadFixtures('view.html');
expect($('#automobile.Id')).toHaveCss({ width: "50px" });
$('#automobile.Id').mouseover();
expect($('#automobile.Id')).toHaveCss({ width: "60px" });
});

You can do this with an end to end test using something like protractor. Jasmine unit tests are not meant to actually have the app fully load and prepare everything like a full end to end test. To achieve this please take a look at the end to end tests in the skeleton-navigation applications.

Related

How to test a target component when it refers to other components' state when it renders

I am writing jest tests. The tested Dashboard component's render shows below,
in Dashboard.jsx
render(){
const {appState,dashboardState,shopFiltersState,shopSortersState}=store.getState();
return (
<div style={appState.primeStyle.dashboard}>
{
(appState.currUser.account==='admin')?
<IconButton iconStyle={shopDetailStyle.iconMenu.icon} style={shopDetailStyle.iconMenu.iconBtn} tooltip={I18n.t('moreInfo')} tooltipPosition="top-center" onClick={this.handleIconAPClick} ><IconInfo /></IconButton>:<div/>
}
</div>
);
}
If I want to test this Dashboard.jsx with different appState, shopFiterssState or shopSortersState, are there good suggestions about how to do it?
I know the existence of mockStore, but I don't think it can be used to modify other component's state in the normal code flow.
Any suggestions are appreciated.

Load image ansyncronously with angular http.get call

This may come off as a bit newb-ish, but I don't really know how to approach this.
Can anyone recommend me a way of delivering and image from a flask backend, after being called by an angular $http.get call?
Brief example of what I am trying to do.
//javascript code
myApp.controller('MyCtrl', function($scope, $http){
$http.get('/get_image/').success(function(data){
$scope.image = data;
});
});
#flask back end
#app.route('/get_image/', methods= ['GET', 'POST'])
def serve_image():
image_binary = get_image_binary() #returns a .png in raw bytes
return image_binary
<!-- html -->
<html ng-app= "myApp">
<div ng-controller= "MyCtrl">
{{ image }}
</div>
</html>
So as you can see, I am attempting to serve a raw-byte .png image from the flask backend, to the frontend.
I've tried something like this
<html>
<img src= "/get_image/">
</html>
But the trouble is, 'get_image_binary' takes a while to run, and the page loads before the image is ready to be served. I want the image to load asyncronously to the page, only when it is ready.
Again, I am sure there are many ways to do this, probably something built into angular itself, but it is sort of difficult to phrase this into a google-able search.
Can't speak to the flask stuff, but below is some AngularJS code.
This directive won't replace the source attribute until after Angular manipulates the DOM and the browser renders (AngularJS : $evalAsync vs $timeout).
HTML:
<div ng-controller="MyController">
<img lazy-load ll-src="http://i.imgur.com/WwPPm0p.jpg" />
</div>
JS:
angular.module('myApp', [])
.controller('MyController', function($scope) {})
.directive('lazyLoad', function($timeout) {
return {
restrict:'A',
scope: {},
link: function(scope, elem, attrs) {
$timeout(function(){ elem.attr('src', attrs.llSrc) });
},
}
});
Same code in a working JSFiddle

I need to do this with ajax

<style>
#number{height: 50px; color: #000; }
</style>
Progress: <div id="number"> </div>
<script type="text/javascript">
var i = 0;
d = 1;
function increment(d) {
if(i<100){
i+=d;
document.getElementById('number').innerHTML = i + '%';
}
else{
document.getElementById('number').innerHTML = 'done' ;
}
}
setInterval('increment(d)', 1000);
</script>
<button type="button" id="button" onclick="d++">Add</button>
<button type="button" onclick="window.location.reload()">Refresh</button>
i'm currently working on a web app with visual studio on asp.net mvc 4. i need to make a partial view that shows a counter that goes from 1 to 100. i added a button that increases by 1 the counter value on every click and another one for refreshing the page. how can i do this using ajax?
AJAX (Asynchronous Javascript and XML) is for making web requests without visible page refreshes. That is not what you should be using this for. You can do this using setTimeout. I have provided a JSFiddle for you to use.
The important bits
In Javascript, you can simulate asynchronous functionality using setTimeout. This function will allow the Javascript to continue executing, and after a given waiting period, will execute the code you provide.
function doSomething() { alert("hello"); }
setTimeout(doSomething, 1000);
This will execute the doSomething() method.
NOTE: You pass the function as a callback. As in doSomething and not doSomething().

qunit reports results before execution is finished

I'm still new to QUnit. There's the snippet
<body>
<div id=qunit></div>
<div id=qunit-fixture>
..
<a title=something href=#>foo</a>
</div>
and the corresponding test case contains
$( 'a').each( function() {
console.debug( this);
// do something
} );
However, QUnit inserts the results in #qunit, including some hyperlinks, which in turn appear in the test case (inside the each). Obviously, content inserted by QUnit should be outside the test's scope. Any suggestion for how to avoid this?
QUnit deals with this by having your place the HTML your test needs inside the qunit-fixture element, so instead of:
$('a').each(function() { ... });
you would do:
$('#qunit-fixture a').each(function() { ... });
in your test case.
This lets you isolate your tests without depending on other page contents. The QUnit documentation provides more information about this methodology.

twitter bootstrap dynamic carousel

I'd like to use bootstrap's carousel to dynamically scroll through content (for example, search results). So, I don't know how many pages of content there will be, and I don't want to fetch a subsequent page unless the user clicks on the next button.
I looked at this question: Carousel with dynamic content, but I don't think the answer applies because it appears to suggest loading all content (images in that case) from a DB server side and returns everything as static content.
My best guess is to intercept the click event on the button press, make the ajax call for the next page of search results, dynamically update the page when the ajax call returns, then generate a slide event for the carousel. But none of this is really discussed or documented on the bootstrap pages. Any ideas welcome.
If you (or anyone else) is still looking for a solution on this, I will share the solution I discovered for loading content via AJAX into the Bootstrap Carousel..
The solution turned out to be a little tricky since there is no way to easily determine the current slide of the carousel. With some data attributes I was able to handle the .slid event (as you suggested) and then load content from another url using jQuery $.load()..
$('#myCarousel').carousel({
interval:false // remove interval for manual sliding
});
// when the carousel slides, load the ajax content
$('#myCarousel').on('slid', function (e) {
// get index of currently active item
var idx = $('#myCarousel .item.active').index();
var url = $('.item.active').data('url');
// ajax load from data-url
$('.item').html("wait...");
$('.item').load(url,function(result){
$('#myCarousel').carousel(idx);
});
});
// load first slide
$('[data-slide-number=0]').load($('[data-slide-number=0]').data('url'),function(result){
$('#myCarousel').carousel(0);
});
Demo on Bootply
I combined #Zim's answer with Bootstrap 4. I hope it will help someone.
First, load just the path of the images:
<div id="carousel" class="carousel slide" data-ride="carousel">
<div class="carousel-inner">
<div class="carousel-item" data-url="/image/1.png"></div>
<div class="carousel-item" data-url="/image/2.png"></div>
<div class="carousel-item" data-url="/image/3.png"></div>
</div>
</div>
Then in JavaScript:
$('document').ready(function () {
const loadCarouselImage = function ($el) {
let url = $el.data('url');
$el.html(function () {
let $img = $('<img />', {
'src': url
});
$img.addClass('d-block w-100');
return $img;
});
);
const init = function () {
let $firstCarousel = $('#carousel .carousel-item:first');
loadCarouselImage($firstCarousel);
$firstCarousel.addClass('active');
$('#productsCarousel').carousel({
interval: 5000
});
};
$('#carousel').on('slid.bs.carousel', function () {
loadCarouselImage($('#carousel .carousel-item.active'));
});
init();
});

Resources