AngularJs - get list of all registered modules - angularjs

Can I get a list of all registered modules at run time?
For example:
// Some code somewhere in some .js file
var module1 = angular.module('module1', []);
// Some code in some other .js file
var module2 = angular.module('module2', []);
// Main .js file
var arrayWithNamesOfAllRegisteredModules = .....
// (result would be: ['module1', 'module2'])

Angular does not provide a way to retrieve the list of registered modules (at least I was not able to find a way in source code). You can however decorate angular.module method to store names in array. Something like this:
(function(orig) {
angular.modules = [];
angular.module = function() {
if (arguments.length > 1) {
angular.modules.push(arguments[0]);
}
return orig.apply(null, arguments);
}
})(angular.module);
Now you can check angular.modules array.
Demo: http://plnkr.co/edit/bNUP39cbFqNLbXyRqMex?p=preview

You can simply do :
console.log(angular.module('ModuleYouWantToInspect').requires);
It should return of an array of strings (dependencies). You can do the same for the output.

Given an angular.element, the $injector.modules array contains the list of registered modules.
e.g.
angular.element(document.body).injector().modules

If you're debugging, I discovered you can get the list by:
Find or add code to invoke run() from any module with any body, say:
angular.module('myModule')
.run(function() {})
Put a breakpoint on the .run, and step into angular.run(). There's an object called "modules" in scope that has all the modules as properties, by name.
This may work with other module methods too, or be accessible from code; I haven't tried very hard to understand the larger picture.

Improving solution
(function(angular) {
var orig = angular.module;
angular.modules = [];
angular.modules.select = function(query) {
var cache = [], reg = new RegExp(query || '.*');
for(var i=0,l=this.length;i< l;i++){
var item = this[i];
if(reg.test(item)){
cache.push(item)
}
}
return cache;
}
angular.module = function() {
var args = Array.prototype.slice.call(arguments);
if (arguments.length > 1) {
angular.modules.push(arguments[0]);
}
return orig.apply(null, args);
}
})(angular);
Now you can select modules:
angular.modules.select('app.modules.*')
Creating modules tree:
var app = angular.module('app.module.users', ['ui.router'...]);
var app = angular.module('app.module.users.edit', ['app.modules.users']);
Your main module app (concat submodules)
angular.module('app', ['ui.bootstrap', 'app.services', 'app.config']
.concat(angular.modules.select('app.module.*')));

in addition to #dfsq answer you can get list of modules with it dependencies
var AngularModules = (function (angular) {
function AngularModules() {
extendAngularModule();
angular.element(document).ready(function () {
getModulesDependencies();
});
}
var extendAngularModule = function () {
var orig = angular.module;
angular.modules = [];
angular.module = function () {
var args = Array.prototype.slice.call(arguments);
var modules = [];
if (arguments.length > 1) {
modules.push(arguments[0]);
}
for (var i = 0; i < modules.length; i++) {
angular.modules.push({
'module': modules[i]
});
}
return orig.apply(null, args);
};
};
var getModulesDependencies = function () {
for (var i = 0; i < angular.modules.length; i++) {
var module = angular.module(angular.modules[i].module);
angular.modules[i].dependencies = module && module.hasOwnProperty('requires') ? module.requires : [];
}
};
return AngularModules;
})(angular);
Usage:
var modules = new AngularModules();

There is a similar question with better answers here https://stackoverflow.com/a/19412176/132610, a summary of what they proposed is:
var app = angular.module('app', []);
# app.service(/**your injections*/) etc
# to access to the list of services + injections
app._invokeQueue #has following form:
[
[
'$provide',
'service',
Arguments[
'serviceName',
[
'$dependency1',
'$dependency2',
function(){}
],
]
]
]

This involves poking at implementation details that may change over time, but you can try this.
Load the page fully.
Set a breakpoint inside angular.module().
Call angular.module() from the console.
When you hit the breakpoint execute print out the modules dictionary console.dir(modules) or if you want to copy it into another editor window.prompt('', JSON.stringify(modules))
This works because behind the scenes angular builds a dictionary of the loaded modules called modules. You also want to wait until it's finished loading all the modules so they're in the dictionary.

Related

Protractor: classes inheritance

I have 3-levels of inheriting classes:
First class inherit ElementArrayFinder, Second class inherit first class. This is my code:
1-st class:
var util = require('util');
var ElementArrayFinder = require('C:/Users/Lilia.Sapurina/AppData/Roaming/npm/node_modules/protractor/lib/element').ElementArrayFinder;
var psComponent = function() {};
util.inherits(psComponent, ElementArrayFinder);
module.exports = psComponent;
2-nd class:
var util = require('util');
var psComponent = require('../lib/psComponent');
var psDateTimePicker = function() {};
util.inherits(psDateTimePicker, psComponent);
psDateTimePicker.prototype.getField = function() {
return element(by.xpath('//div[1]/table/tbody/tr[2]/td[1]/div/input'));
};
psDateTimePicker.prototype.getButton = function() {
return element(by.css('td > a.b-button.b-button_only_icon'));
};
exports.psDateTimePicker = new psDateTimePicker();
I can use it in my code in this way:
fdescribe('lala', function () {
var psDateTimePicker = require('../lib/psDateTimePicker').psDateTimePicker;
beforeEach(function(){
browser.get('ng-components/examples/ps-date-time-picker.html');
});
it('test', function () {
expect(psDateTimePicker.getField().getAttribute("value")).toEqual(6);
});
});
But I want to make global interface and make code construction looks like:
fdescribe('lala', function () {
var psComponents = require('../lib/psComponent');
beforeEach(function(){
browser.get('ng-components/examples/ps-date-time-picker.html');
});
it('test', function () {
expect(psComponents.psDateTimePicker.getField().getAttribute("value")).toEqual(6);
});
});
Does anybody know how I can organize it? I tried to use getInstanceOf(), but its not working. Also it isn't very conveniently.
If you want to create a namespace for all your components, you can just create an extra module responsible for that:
// psComponents.js
module.exports = {
psDateTimePicker: require('../lib/psDateTimePicker').psDateTimePicker,
psAnotherComponent: require('../lib/psAnotherComponent').psAnything
};
And use it pretty like the same you want:
var psComponents = require('../lib/psComponents');
expect(psComponents.psDateTimePicker.getField().getAttribute("value")).toEqual(6);
This is much simpler than what you've tried to do - trying to access children from a parent - there is no an easy way to achieve it and usually there is no reason to. Prototypes are just boilerplates to create new independent instances, which are not supposed to be connected to each other. Pretty much the same with prototype inheritance: you just extend that boilerplate, but child and parent instances a gonna remain independent.
Not entirely sure what you're looking for but maybe something along these line...?
var util = require('util');
var ElementArrayFinder = require('C:/Users/Lilia.Sapurina/AppData/Roaming/npm/node_modules/protractor/lib/element').ElementArrayFinder;
var psDateTimePicker = require('../lib/psDateTimePicker').psDateTimePicker;
var PsComponent = function() {};
util.inherits(PsComponent, ElementArrayFinder);
PsComponent.prototype = util;
PsComponent.prototype = psDateTimePicker;
module.exports = new PsComponent();
Then...
describe('lala', function () {
var psComponents = require('../lib/psComponents');
beforeEach(function(){
browser.get('ng-components/examples/ps-date-time-picker.html');
});
it('test', function() {
expect(psComponents.getField().getAttribute("value")).toEqual(6);
});
});

Using angular functions ($q) in protractor

I want to use the $q service of angular in my e2e tests. (I want to get the texts of a bunch of elements via getText() which returns a promise. After all promises are resolved, I want to test the list. So I want to use $q.all() etc.)
angular.injector(['myApp']).get('$q'); results in "ReferenceError: angular is not defined"
Installing angular via node and then var angular = require("angularjs"); results in "Error: Cannot find module 'angular'"
Also, inserting a browser.waitForAngular() does not help there.
Using the inject(function($q) {}) syntax has the same problem.
How can I use such angular functions in protractor?
edit:
Here's the very naive version of what I want to achieve
var collectEntries = function(containers) {
var entries = {};
containers.each(function (container) {
var title = container.element(by.tagName('h2'));
title.getText().then(function (text) {
var key = getSomeKey();
var entry = processEntry(text);
entries[key] = entry;
});
});
return entries;
};
That works in principle, at some point in time entries contains all data. However, I need to wait for that moment. What I would do is create and return a promise that gets resolved as soon as all getText promises are resolved.
e.g.
var deferred = $q.defer();
$q.all(getTextPromises).then(function () {
deferred.resolve(entries);
});
return deferred.promise;
From the looks of your code containers is a list of elementFinders? (i.e. var containers = [element(by.x), element(by.y), element(by.z)]):
Using q: (you need to add q as dependency in package.json first)
var q = require('q');
var collectEntries = function(containers) {
var entries = {};
containers.each(function (container) {
var deferred = q.defer();
var title = container.element(by.tagName('h2'));
title.getText().then(function (text) {
deferred.resolve(processEntry(text));
});
entries[getSomeKey()] = deferred.promise();
});
return q.all(entries);
};
expect(collectEntries).toBe({key1: 'title1', key2: 'title2'})
But protractor knows promise itself (and it's preferably that you don't mix protractor's promise with q promise unless you know what you're doing):
var collectEntries = function(containers) {
var entries = {};
containers.each(function (container) {
entries[getSomeKey()] = container.element(by.tagName('h2')).
getText().then(function (text) {
return processEntry(text);
});
});
return protractor.promise.fullyResolved(entries);
};
expect(collectEntries).toBe({key1: 'title1', key2: 'title2'})
If your containers are found using a single selector (i.e. var containers = element.all(by.xyz)), it's even easier:
var collectEntries = function(containers) {
return containers.reduce(function(entries, elem) {
return elem.getText().then(function(text) {
entries[getSomeKey()] = processEntry(text);
return entries;
});
}, {});
};
expect(collectEntries).toBe({key1: 'title1', key2: 'title2'})

Inject module dynamically, only if required

I'm using Require.js in combination with Angular.js.
Some controllers need huge external dependencies which others don't need, for example, FirstController requires Angular UI Codemirror. That's a extra 135 kb, at least:
require([
"angular",
"angular.ui.codemirror" // requires codemirror itself
], function(angular) {
angular.module("app", [ ..., "ui.codemirror" ]).controller("FirstController", [ ... ]);
});
I don't want to have to include the directive and the Codemirror lib everytime my page loads just to make Angular happy.
That's why I'm right now loading the controller only when the route is hit, like what's done here.
However, when I need something like
define([
"app",
"angular.ui.codemirror"
], function(app) {
// ui-codemirror directive MUST be available to the view of this controller as of now
app.lazy.controller("FirstController", [
"$scope",
function($scope) {
// ...
}
]);
});
How can I tell Angular to inject ui.codemirror module (or any other module) in the app module aswell?
I don't care if it's a hackish way to accomplish this, unless it involves modifying the code of external dependencies.
If it's useful: I'm running Angular 1.2.0.
I have been trying to mix requirejs+Angular for some time now. I published a little project in Github (angular-require-lazy) with my effort so far, since the scope is too large for inline code or fiddles. The project demonstrates the following points:
AngularJS modules are lazy loaded.
Directives can be lazy loaded too.
There is a "module" discovery and metadata mechanism (see my other pet project: require-lazy)
The application is split into bundles automatically (i.e. building with r.js works)
How is it done:
The providers (e.g. $controllerProvider, $compileProvider) are captured from a config function (technique I first saw in angularjs-requirejs-lazy-controllers).
After bootstraping, angular is replaced by our own wrapper that can handle lazy loaded modules.
The injector is captured and provided as a promise.
AMD modules can be converted to Angular modules.
This implementation satisfies your needs: it can lazy-load Angular modules (at least the ng-grid I am using), is definitely hackish :) and does not modify external libraries.
Comments/opinions are more than welcome.
(EDIT) The differentiation of this solution from others is that it does not do dynamic require() calls, thus can be built with r.js (and my require-lazy project). Other than that the ideas are more or less convergent across the various solutions.
Good luck to all!
Attention: use the solution by Nikos Paraskevopoulos, as it's more reliable (I'm using it), and has way more examples.
Okay, I have finally found out how to achieve this with a brief help with this answer.
As I said in my question, this has come to be a very hacky way. It envolves applying each function in the _invokeQueue array of the depended module in the context of the app module.
It's something like this (pay more attention in the moduleExtender function please):
define([ "angular" ], function( angular ) {
// Returns a angular module, searching for its name, if it's a string
function get( name ) {
if ( typeof name === "string" ) {
return angular.module( name );
}
return name;
};
var moduleExtender = function( sourceModule ) {
var modules = Array.prototype.slice.call( arguments );
// Take sourceModule out of the array
modules.shift();
// Parse the source module
sourceModule = get( sourceModule );
if ( !sourceModule._amdDecorated ) {
throw new Error( "Can't extend a module which hasn't been decorated." );
}
// Merge all modules into the source module
modules.forEach(function( module ) {
module = get( module );
module._invokeQueue.reverse().forEach(function( call ) {
// call is in format [ provider, function, args ]
var provider = sourceModule._lazyProviders[ call[ 0 ] ];
// Same as for example $controllerProvider.register("Ctrl", function() { ... })
provider && provider[ call[ 1 ] ].apply( provider, call[ 2 ] );
});
});
};
var moduleDecorator = function( module ) {
module = get( module );
module.extend = moduleExtender.bind( null, module );
// Add config to decorate with lazy providers
module.config([
"$compileProvider",
"$controllerProvider",
"$filterProvider",
"$provide",
function( $compileProvider, $controllerProvider, $filterProvider, $provide ) {
module._lazyProviders = {
$compileProvider: $compileProvider,
$controllerProvider: $controllerProvider,
$filterProvider: $filterProvider,
$provide: $provide
};
module.lazy = {
// ...controller, directive, etc, all functions to define something in angular are here, just like the project mentioned in the question
};
module._amdDecorated = true;
}
]);
};
// Tadaaa, all done!
return {
decorate: moduleDecorator
};
});
After this has been done, I just need, for example, to do this:
app.extend( "ui.codemirror" ); // ui.codemirror module will now be available in my application
app.controller( "FirstController", [ ..., function() { });
The key to this is that any modules your app module depends on also needs to be a lazy loading module as well. This is because the provider and instance caches that angular uses for its $injector service are private and they do not expose a method to register new modules after initialization is completed.
So the 'hacky' way to do this would be to edit each of the modules you wish to lazy load to require a lazy loading module object (In the example you linked, the module is located in the file 'appModules.js'), then edit each of the controller, directive, factory etc calls to use app.lazy.{same call} instead.
After that, you can continue to follow the sample project you've linked to by looking at how app routes are lazily loaded (the 'appRoutes.js' file shows how to do this).
Not too sure if this helps, but good luck.
There is a directive that will do this:
https://github.com/AndyGrom/loadOnDemand
example:
<div load-on-demand="'module_name'"></div>
The problem with existing lazy load techniques is that they do things which I want to do by myself.
For example, using requirejs, I would like to just call:
require(['tinymce', function() {
// here I would like to just have tinymce module loaded and working
});
However it doesn't work in that way. Why? As I understand, AngularJS just marks the module as 'to be loaded in the future', and if, for example, I will wait a bit, it will work - I will be able to use it. So in the function above I would like to call some function like loadPendingModules();
In my project I created simple provider ('lazyLoad') which does exactly this thing and nothing more, so now, if I need to have some module completely loaded, I can do the following:
myApp.controller('myController', ['$scope', 'lazyLoad', function($scope, lazyLoad) {
// ........
$scope.onMyButtonClicked = function() {
require(['tinymce', function() {
lazyLoad.loadModules();
// and here I can work with the modules as they are completely loaded
}]);
};
// ........
});
here is link to the source file (MPL license):
https://github.com/lessmarkup/less-markup/blob/master/LessMarkup/UserInterface/Scripts/Providers/lazyload.js
I am sending you sample code. It is working fine for me. So please check this:
var myapp = angular.module('myapp', ['ngRoute']);
/* Module Creation */
var app = angular.module('app', ['ngRoute']);
app.config(['$routeProvider', '$controllerProvider', function ($routeProvider, $controllerProvider) {
app.register = {
controller: $controllerProvider.register,
//directive: $compileProvider.directive,
//filter: $filterProvider.register,
//factory: $provide.factory,
//service: $provide.service
};
// so I keep a reference from when I ran my module config
function registerController(moduleName, controllerName) {
// Here I cannot get the controller function directly so I
// need to loop through the module's _invokeQueue to get it
var queue = angular.module(moduleName)._invokeQueue;
for (var i = 0; i < queue.length; i++) {
var call = queue[i];
if (call[0] == "$controllerProvider" &&
call[1] == "register" &&
call[2][0] == controllerName) {
app.register.controller(controllerName, call[2][1]);
}
}
}
var tt = {
loadScript:
function (path) {
var result = $.Deferred(),
script = document.createElement("script");
script.async = "async";
script.type = "text/javascript";
script.src = path;
script.onload = script.onreadystatechange = function (_, isAbort) {
if (!script.readyState || /loaded|complete/.test(script.readyState)) {
if (isAbort)
result.reject();
else {
result.resolve();
}
}
};
script.onerror = function () { result.reject(); };
document.querySelector(".shubham").appendChild(script);
return result.promise();
}
}
function stripScripts(s) {
var div = document.querySelector(".shubham");
div.innerHTML = s;
var scripts = div.getElementsByTagName('script');
var i = scripts.length;
while (i--) {
scripts[i].parentNode.removeChild(scripts[i]);
}
return div.innerHTML;
}
function loader(arrayName) {
return {
load: function ($q) {
stripScripts(''); // This Function Remove javascript from Local
var deferred = $q.defer(),
map = arrayName.map(function (obj) {
return tt.loadScript(obj.path)
.then(function () {
registerController(obj.module, obj.controller);
})
});
$q.all(map).then(function (r) {
deferred.resolve();
});
return deferred.promise;
}
};
};
$routeProvider
.when('/first', {
templateUrl: '/Views/foo.html',
resolve: loader([{ controller: 'FirstController', path: '/MyScripts/FirstController.js', module: 'app' },
{ controller: 'SecondController', path: '/MyScripts/SecondController.js', module: 'app' }])
})
.when('/second', {
templateUrl: '/Views/bar.html',
resolve: loader([{ controller: 'SecondController', path: '/MyScripts/SecondController.js', module: 'app' },
{ controller: 'A', path: '/MyScripts/anotherModuleController.js', module: 'myapp' }])
})
.otherwise({
redirectTo: document.location.pathname
});
}])
And in HTML Page:
<body ng-app="app">
<div class="container example">
<!--ng-controller="testController"-->
<h3>Hello</h3>
<table>
<tr>
<td>First Page </td>
<td>Second Page</td>
</tr>
</table>
<div id="ng-view" class="wrapper_inside" ng-view>
</div>
<div class="shubham">
</div>
</div>

AngularJS nested functions in services and dependency injection?

Ok I have two modules which depend upon each other both modules have services, directives, ctrl's etc, now my question is how do i get values assigned in the nested function of the second module's service in the controller of the first service, I have added the dependencies to the first controller but i can't see to get at the nested functions variables to then manipulate them in the ctrl of the first module here's the code(considerably cut down):
angular.module("mainapp", [
"dateSheet",
"bookingApp"
]).controller("AppCtrl", [
"$scope",
"$attrs",
"Booking",
function (scope, source, attributes, AppDataLoader, booking, Booking) {
//HERE I NEED TO BE ABLE TO DO SOMETHING LIKE THIS
var getdaiyrate = function(){
var dumpDailyRates = scope.Booking.getalldates.getrates.dailyPrice
console.log(dumpDailyRates);
}
}
]);
angular.module("bookingApp", ["bookingApp.services",]);
angular.module("bookingApp.services").service("Booking", [
function(){
function getRate(source, dateSheet, dateSheetCtrl, expect, $$childTail, appData) {
var dateValue = $("Date", source).text() || "";
if (!dateValue) {
return null;
}
var dailyPrice = $("DailyPrice", source).text() || "";
var weeklyPrice = $("WeeklyPrice", source).text() || "";
var monthlyPrice = $("MonthlyPrice", source).text() || "";
var isAvailable = $("IsAvailable", source).text() === "1";
var minimumStay = Number($("MinimumStay", source).text());
if (isNaN(minimumStay)) {
minimumStay = DEFAULT_MINIMUM_STAY;
}
return {
date: new Date(dateValue),
dailyPrice: dailyPrice,
weeklyPrice: weeklyPrice,
monthlyPrice: monthlyPrice,
reserved: !isAvailable,
minimumStay: minimumStay
};
}
return {
getalldates: function(source, $scope){
return getRate(source, scope);
}
};
}
]);
The above doesn't work what am i doing wrong....
Could someone please send me in the direction of a decent tutorial that deals with a end to end app using various modules and dependencies??
Chris
You need to inject the service module into the module that you want to use it in. So the first line becomes
angular.module("mainapp", ["dateSheet","bookingApp","bookingApp.services"])
Also i don't see the creation of bookingApp.services so this may also be required
angular.module("bookingApp.services",[]);
and the invocation would be something like this
var dumpDailyRates = Booking.getalldates(sourceParameter, $scope);

Missing injection for test (unkown provider)

I am trying to write unit tests for my Angular.js application but I cannot manage to inject what I need (it is not able to find a suitable provider).
Does anyone see what I missed?
Firefox 21.0 (Linux) filter staticList should convert static list object into its display value FAILED
Error: Unknown provider: staticListProvider <- staticList in /path/to/my-app/public/third-party/angular/angular.js (line 2734)
createInjector/providerInjector<#/path/to/my-app/public/third-party/angular/angular.js:2734
getService#/path/to/my-app/public/third-party/angular/angular.js:2862
createInjector/instanceCache.$injector<#/path/to/my-app/public/third-party/angular/angular.js:2739
getService#/path/to/my-app/public/third-party/angular/angular.js:2862
invoke#/path/to/my-app/public/third-party/angular/angular.js:2880
workFn#/path/to/my-app/test/lib/angular/angular-mocks.js:1778
angular.mock.inject#/path/to/my-app/test/lib/angular/angular-mocks.js:1764
#/path/to/my-app/test/unit/filtersSpec.js:19
#/path/to/my-app/test/unit/filtersSpec.js:16
#/path/to/my-app/test/unit/filtersSpec.js:3
The application:
angular.module('myApp', ['myAppFilters', 'ui.bootstrap', '$strap.directives']).
// Some other stuff
The filters:
"use strict";
angular.module('myAppFilters', []).
filter('staticList', function () {
return function (listItem) {
if (!listItem) {
return '';
}
return listItem.value;
};
});
The test:
'use strict';
describe('filter', function () {
beforeEach(angular.module('myAppFilters'));
describe('staticList', function () {
it('should convert static list object into its display value',
inject(function (staticList) {
expect(undefined).toBe('');
expect({key: 'A', value: 'B'}).toBe('B');
}));
});
});
The Karma configuration:
basePath = '../';
files = [
JASMINE,
JASMINE_ADAPTER,
'public/third-party/jquery/*.js',
'public/third-party/angular/angular.js',
'public/third-party/angular/i18n/angular-*.js',
'public/third-party/moment/moment.min.js',
'public/third-party/moment/moment-*.js',
'public/js/**/*.js',
'test/lib/**/*.js',
'test/unit/**/*.js'
];
colors = true;
autoWatch = true;
browsers = ['Firefox'];
junitReporter = {
outputFile: 'test_out/unit.xml',
suite: 'unit'
};
If anybody wants to see the full code, the application repository is here: https://github.com/adericbourg/GestionCourrier
Thanks a lot,
Alban
In your inject code
it('should convert static list object into its display value',
inject(function (staticList) {
expect(undefined).toBe('');
expect({key: 'A', value: 'B'}).toBe('B');
}));
replace "inject(function (staticList)" with "inject(function (staticListFilter)". This is some random convention angular is following. You can check comments on this page for more info http://docs.angularjs.org/tutorial/step_09
I faced similar problem, but in my case my filter name contained suffix 'Filter' which caused the same injection problem.
.filter('assetLabelFilter', function(){
return function(assets, selectedLabels){
// Implementation here
};
});
I was finally able to solve the problem by manually injecting the filter to my test
'use strict';
describe('assetLabelFilter', function() {
beforeEach(module('filters.labels'));
var asset1 = {labels: ['A']};
var asset2 = {labels: ['B']};
var asset3 = {labels: []};
var asset4 = {labels: ['A', 'B']};
var assets = [asset1, asset2, asset3, asset4];
var assetLabelFilter;
beforeEach(inject(function($filter) {
assetLabelFilter = $filter('assetLabelFilter');
}));
it('should return only assets with selected label', function() {
var selectedLabels = ['B'];
expect(assetLabelFilter(assets, selectedLabels)).toEqual([asset2, asset4]);
});
});
The nice answer above made me realize that in order to use the angular tutorial way:
it('should ', inject(function(assetLabelFilter) {
var selectedLabels = ['B'];
expect(assetLabelFilter(assets, selectedLabels)).toEqual([asset2, asset4]);
}));
The filter name can't have the suffix 'Filter' because it is magic word as mentioned in the answer above.
To demonstrate the scenario I also created a Plunker

Resources