Get routerLink properties from HTML in Angular unit test - javascript

I have following HTML property:
<ul>
<li class="nav-item" routerLinkActive="active">
<a class="nav-link" [routerLink]="['/home']">Home</a>
</li>
</ul>
I want now to get the href as a value in the unit test. So far I have in my test-case:
it('should navigate have login navigation', () => {
const debugElements = fixture.debugElement.queryAll(By.css('a.nav-link'));
debugElements.forEach(x => console.log(x.properties['href']));
});
});
But that is every time undefined. How do I fetch the href from the rounterLink directive? Incidentally, I don't need to do fixture.detectChanges(); Since I don't use lifecycle-hooks in this particular comp.

You actually have to run fixture.detectChanges(). This is not limited to lifecycle hooks but concerns change detection in general (so pretty much any magic that Angular does).
I've created a Stackblitz demonstrating that the test is failing without detectChanges and running with it.

Related

Angular 2 Routing Guide - Plunker Example not working with IE 11.096 on Windows 7

I have been using some of the examples from the Angular router guide (with lazy loading) per the link: https://angular.io/docs/ts/latest/guide/router.html
I am unable to get the Plunker example to run. This is the link to my copy of the example: https://plnkr.co/edit/a4ACZxIxKz0kD2AOZYjL?p=preview. The only changes I have made have been to add a app/app.component.html file.
Does anyone know if there is a problem with this code? If so, what needs to be done to make it work? If the code is fine what could I be doing wrong that would not allow me to run the code? I have run many Plunker examples before.
Once I get this code to work I then want to change it to have components use the templateUrl property so I can demonstrate another problem I am having with routing.
Code for the HTML is:
<h1 class="title">Angular Router</h1>
<nav>
<a routerLink="/crisis-center" routerLinkActive="active">Crisis Center</a>
<a routerLink="/heroes" routerLinkActive="active">Heroes</a>
<a routerLink="/admin" routerLinkActive="active">Admin</a>
<a routerLink="/login" routerLinkActive="active">Login</a>
<a [routerLink]="[{ outlets: { popup: ['compose'] } }]">Contact</a>
</nav>
<router-outlet></router-outlet>
<router-outlet name="popup"></router-outlet>

AureliaJS - replacing looped elements with a template (passing values?)

I have found https://sean-hunter.io/2016/10/23/inter-component-communication-with-aurelia/ where it is explained how simple communication of values can be made between a parent and a child template.
Now, I'm trying to apply that to the contact manager tutorial:
http://aurelia.io/hub.html#/doc/article/aurelia/framework/latest/contact-manager-tutorial/1
... also on https://github.com/aurelia/app-contacts/tree/master/src - in particular to the looped contact items, but I cannot get it to work.
I have made gists as an example, which can run on gist.run (note, gist.run seems to only work in Chrome, not in Firefox 50 yet - but you can replace gist.run/?id= with gist.github.com/ and look at the code):
Copy of original contacts manager app (works) - https://gist.run/?id=c73b047c8184c052b4c61c69febb33d8
My changes in the app (do not work) - https://gist.run/?id=47c4f1c053adbdf46f6a33413dd12d3d
This is what I'm trying to do: in the original contacts app, there is this in src/contact-list.html which works fine:
<template>
<div class="contact-list">
<ul class="list-group">
<li repeat.for="contact of contacts" class="list-group-item ${contact.id === $parent.selectedId ? 'active' : ''}">
<a route-href="route: contacts; params.bind: {id:contact.id}" click.delegate="$parent.select(contact)">
<h4 class="list-group-item-heading">${contact.firstName} ${contact.lastName}</h4>
<p class="list-group-item-text">${contact.email}</p>
</a>
</li>
</ul>
</div>
</template>
Now, I'd like to replace the inner elements of the "looped" li - that is, the a with the h4 and the p - with a new template.
So, I made src/contact-list-item.html:
<template>
<a route-href="route: contacts; params.bind: {id:theContact.id}" click.delegate="$parent.$parent.select(theContact)">
<h4 class="list-group-item-heading">${theContact.firstName} ${theContact.lastName}</h4>
<p class="list-group-item-text">${theContact.email}</p>
</a>
</template>
... and src/contact-list-item.js:
import {bindable} from 'aurelia-framework';
export class ContactListItem {
#bindable theContact;
}
... and changed src/contact-list.html as:
<template>
<require from="./contact-list-item"></require>
<div class="contact-list">
<ul class="list-group">
<li repeat.for="contact of contacts" class="list-group-item ${contact.id === $parent.selectedId ? 'active' : ''}">
<contact-list-item theContact.bind="contact"></contact-list-item>
</li>
</ul>
</div>
</template>
Basically, I've made a property in the contact-list-item class called theContact, and I'd like to bind it to the contact which is the looper variable in the repeat.for="contact of contacts" -- unfortunately, this doesn't work, as the data is not propagated (and so the contact names are empty). Also, the clicks on contact fiels do not propagate to show the details, even if I've changed click.delegate="$parent.select(contact)" to click.delegate="$parent.$parent.select(theContact)" in the new template.
What do I have to do, in order to have the data propagate form the li repeate.for loop, down to the new replacement template - and to have the app react on clicks on the new template?
Quick answer:
In contact-list.html, change:
<contact-list-item theContact.bind="contact"></contact-list-item>
to:
<contact-list-item the-contact.bind="contact"></contact-list-item>
Explanation:
HTML is not case-sensitive, but the convention is to use only lower-case letters. To respect that, Aurelia converts all camelCase variables to dash-case parameters and element names when interfacing with your HTML code.
More Information:
Dwayne Charrington wrote a good blog about this topic here:
http://ilikekillnerds.com/2016/06/dont-get-skewered-kebab-case-aurelia/

How to add/activate loading spinner near tab name(title) when I make an api call in angular/Javascript

I am trying to figure out a way to show loading spinner near tab name as shown in the image below whenever I make a api call in angualrJS/javascript.
Normally whenever we refresh the page it is activated , but want to know if we could activate it using javascript or not ?
I have done something similar using bootstrap and font awesome icons
<ul class="nav nav-tabs">
<li role="presentation" class="active">
<a showtab="" href="#myTab" data-toggle="tab">
<i class="fa fa-refresh fa-spinner" data-ng-if="isLoadingData"></i>
My Tab
</a>
</li>
...
</ul>
Above, showtab is an angular directive for tabs and isLoadingData is a flag that I said before making the API call in angular and unset it on a response from API as below:
$scope.isLoadingData = true;
myPromiseGetObj.then(function(data){
$scope.listOfClosedKits = data.data.data;
$scope.isLoadingData = false;
callback(data.data);
});
myPromisePostObj is my $http get object.
Please let me know if you are stuck somewhere :)
EDITED:
To my knowledge, I dont think it could be done, instead you can use your own custom logic to show loading icons when you make API calls.

GitHub API throws error when I don't make any GitHub API calls

I have a website written with AngularJS that I have wrapped in end-to-end tests with Protractor. On this site, I have several links to GitHub repositories for said website. I have several end-to-end tests that click those links and verify that they take you to the correct page. I also have assertions at the end of each test that verifies that no javascript errors were thrown.
Occasionally, when the tests run, I see the following error in the test results:
<failure type="toBe" message="Expected 'https://github.com/DnDGen/CharacterGen 0:0 Fetch API cannot load https://api.github.com/_private/browser/stats. ' to be ''."><![CDATA[Error: Failed expectation
at app.assertNoErrors (C:\Users\Cid the Coatrack\Documents\Programming\Projects\DNDGenSite\Tests\Integration\Views\commonTestFunctions.js:17:47)
at [object Object].promise.ControlFlow.runInFrame_ (C:\Users\Cid the Coatrack\Documents\Programming\Projects\DNDGenSite\node_modules\protractor\node_modules\selenium-webdriver\lib\webdriver\promise.js:1877:20)
at [object Object].promise.Callback_.goog.defineClass.notify (C:\Users\Cid the Coatrack\Documents\Programming\Projects\DNDGenSite\node_modules\protractor\node_modules\selenium-webdriver\lib\webdriver\promise.js:2464:25)
at [object Object].promise.Promise.notify_ (C:\Users\Cid the Coatrack\Documents\Programming\Projects\DNDGenSite\node_modules\protractor\node_modules\selenium-webdriver\lib\webdriver\promise.js:563:12)
at Array.forEach (native)
at Object.goog.array.forEach (C:\Users\Cid the Coatrack\Documents\Programming\Projects\DNDGenSite\node_modules\protractor\node_modules\selenium-webdriver\lib\goog\array\array.js:203:43)
at [object Object].promise.Promise.notifyAll_ (C:\Users\Cid the Coatrack\Documents\Programming\Projects\DNDGenSite\node_modules\protractor\node_modules\selenium-webdriver\lib\webdriver\promise.js:552:16)
at goog.async.run.processWorkQueue (C:\Users\Cid the Coatrack\Documents\Programming\Projects\DNDGenSite\node_modules\protractor\node_modules\selenium-webdriver\lib\goog\async\run.js:125:21)
at runMicrotasksCallback (node.js:337:7)]]>
</failure>
This is particularly confusing because I am making no API calls to GitHub at all - I merely place hyperlinks on the page for the user to click:
<ul class="nav navbar-nav navbar-right">
<li class="dropdown">
<a id="collapsedGithubLinks" href="#" class="dropdown-toggle" data-toggle="dropdown">GitHub <span class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
<li><a id="githubOrganizationLink" href="https://github.com/DnDGen">The DnDGen Project</a></li>
<li class="divider"></li>
<li><a id="githubDiceLink" href="https://github.com/DnDGen/RollGen">RollGen</a></li>
<li><a id="githubEquipmentLink" href="https://github.com/DnDGen/TreasureGen">TreasureGen</a></li>
<li><a id="githubCharacterLink" href="https://github.com/DnDGen/CharacterGen">CharacterGen</a></li>
<li><a id="githubEncounterLink" href="https://github.com/DnDGen/EncounterGen">EncounterGen</a></li>
<li><a id="githubDungeonLink" href="https://github.com/DnDGen/DungeonGen">DungeonGen</a></li>
<li><a id="githubSiteLink" href="https://github.com/DnDGen/DNDGenSite">This Site</a></li>
</ul>
</li>
<li class="padding-right"><a id="officialDndLink" href="http://dnd.wizards.com/">Official D&D Site</a></li>
</ul>
What is even stranger is that the test that fails is not consistent. Sometimes, all tests will pass. Other times, several tests will fail. And the tests that fail are not related to those links - sometimes tests asserting that the brand is shown in the navbar, with no relation or reference to the links at all, will fail for the same API reason.
I have yet to see this error ever occur on the live site. I want to know what is causing this to sporadically occur and how I can fix it.
UPDATE:
Here is the code that I am using to assert that there are no errors:
function assertNoErrors(browserLog) {
for (var i = 0; i < browserLog.length; i++)
expect(browserLog[i].message).toBe('');
expect(browserLog.length).toBe(0);
}
This is called this way:
afterEach(function () {
browser.manage().logs().get('browser').then(assertNoErrors);
});
Update 2:
I should also clarify that any test that navigates outside of my site (i.e., tests that click the GitHub links) do not check for errors, because I did not want tests to fail because of errors on pages that I do not write and control. The tests that do fail stay purely internal to my web app, and almost never interact with the github links at all.
Here is an example of one of the tests that fails randomly (it is not always this one, nor does this one fail all the time)
it('shows the brand', function () {
expect(element(by.css('.navbar-brand')).isDisplayed()).toBeTruthy();
});
For the reference, this is the HTML for that object
<div class="navbar-header">
<a class="navbar-brand" href="~/">DnDGen</a>
</div>
This is a bit of an educated guess, but if you are clicking the links and navigating to github, and your own code does not make a call to https://api.github.com/_private/browser/stats, these errors are probably from a github page and not your own.
I don't have an elegant solution for filtering these out off the top of my head unfortunately. You could not assert there are no errors in the console on tests that interact with third party sites.

batman.js data-route adding characters to url

I have a html template doing this.
<ul id="things">
<li data-foreach-thing="Thing.all" data-mixin="animation">
<a data-route="routes.things[thing].new" data-bind="thing.id"></a>
</li>
</ul>
The data-route attribute is returning a url like this:
http://localhost:3000/#!/things/new
I don't know why it is adding the #!
I'm using batman.js 0.9 with rails 3.1
Any help figuring this out is be appreciated, thanks.
Here's a good description of hash bang urls hash bang urls. This is normal for batman to do this (pretty much all javascript frameworks do this). You can enable "pushstate:true" which will disable it (however it will fall back to hash bang if you're on a legacy browser).
Regarding your batman.js view not being rendered, I ran into a similar issue. I didn't have an error in my chrome console, however the view wasn't being rendered. You need to make sure you have a data-yield attribute for your view to attach to.
For example:
<div id="container" data-yield="main">
</div>
Excerpt from batman.js github:
Now when you navigate to /#!/faq/what-is-art, the dispatcher runs this
faq action with {questionID: "what-is-art"}. It also makes an implicit
call to #render, which by default will look for a view at
/views/app/faq.html. The view is rendered within the main content
container of the page, which is designated by setting
data-yield="main" on some tag in the layout's HTML. You can prevent
this implicit rendering by calling #render false in your action.
Are you trying to show a link to the show action for the thing? It should look like this if you are:
<ul id="things">
<li data-foreach-thing="Thing.all" data-mixin="animation">
<a data-route="routes.things[thing]" data-bind="thing.id"></a>
</li>
</ul>
Here's an example of some code I'm using (the order of the data- attributes doesn't matter):
<div data-foreach-section="sections" data-mixin="animation">
<a data-bind="section.SectionId" data-route="routes.sections[section]"></a>
<p data-bind="section.Name"></p>
</div>

Categories