Как шпионить за методом в области, которая не привязана

Я пытаюсь проверить, вызывается ли метод removePlayer в следующем компоненте при удалении игрока с помощью: spyOn(scope, 'removePlayer').and.callThrough(); и ожидать(scope.removePlayer).toHaveBeenCalled(); но получил следующую ошибку: «Ошибка: метод removePlayer () не существует. Использование: spyOn (,)», как я могу этого добиться, пожалуйста?

.component("playerList", {
            templateUrl: "src/js/player/player.html",
            bindings: {
                list: '<'
            },
            controller: function() {
                this.removePlayer = function(index) {
                    console.log('Remove player with index : ', index);
                    if (index > -1) {
                        this.list.splice(index, 1);
                    }
                };
            }
        });

С помощью следующего теста:

beforeEach(inject(function($rootScope, $compile) {
    scope = $rootScope.$new();
    scope.list = angular.copy(playersList);
    element = angular.element('<player-list list="list"></player-list>');
    element = $compile(element)(scope);

    scope.$apply();
}));

it('should render the text', function() {
    // spyOn(scope, 'removePlayer').and.callThrough();
    var title = element.find('h1');
    var deleteBtn = element[0].querySelector('button');
    expect(title.text()).toBe('This table contains ' + playersList.length + ' player.');
    deleteBtn.click();
    // expect(scope.removePlayer).toHaveBeenCalled();
    expect(title.text()).toBe('This table contains ' + (playersList.length - 1) + ' player.');
});

вот шаблон:

<div class="container">
    <h1 class- "player-table-title">This table contains {{ $ctrl.list.length }} players[![enter image description here][1]][1].</h1>
    <table class="table table-striped">
        <thead>
            <tr>
                <th>Name</th>
                <th>Position</th>
                <th>Team</th>
                <th>Actions</th>
            </tr>
        </thead>
        <tbody>
            <tr ng-repeat="player in $ctrl.list">
                <td>{{ player.name }}</td>
                <td>{{ player.position }}</td>
                <td>{{ player.team }}</td>
                <td>
                    <button type="button" class="btn btn-danger btn-sm" ng-click="$ctrl.removePlayer($index)">
                        <span class="glyphicon glyphicon-trash"></span>
                    </button>
                </td>
            </tr>
        </tbody>
    </table>
</div>

Вот как приложение выглядит в браузере:

введите здесь описание изображения


person Youness Houdass    schedule 19.08.2017    source источник


Ответы (2)


Этот метод является методом контроллера, а не областью действия. Кстати, у компонентов нет области видимости.

Попробуйте получить контроллер вашего компонента вот так (не забудьте ввести $componentController)

controller = $componentController('playerList', {$scope: scope});

А затем замените scope на controller в функции spyOn

spyOn(controller, 'removePlayer').and.callThrough();
....
expect(controller.removePlayer).toHaveBeenCalled();
person NechiK    schedule 19.08.2017
comment
Извините, не заменяйте область действия контроллером в первом ответе. Я отредактировал это. - person NechiK; 19.08.2017
comment
Спасибо за ваш ответ, я знаю о $componentController, но он не будет работать для меня, я намерен шпионить за методом removePlayer, когда я нажимаю кнопку удаления, $componentController не будет обрабатывать этот случай для меня :) - person Youness Houdass; 19.08.2017
comment
Я пытаюсь сделать что-то вроде этого: 1 - spyOn(scope, 'removePlayer').and.callThrough(); 2-deleteBtn.click(); (это вызывает функцию removePlayer) 3- expect(scope.removePlayer).toHaveBeenCalled(); - person Youness Houdass; 19.08.2017
comment
Ваша функция определена в контроллере. Почему вы пытаетесь шпионить за ним по прицелу? - person NechiK; 19.08.2017
comment
$componentController нужен для получения контроллера вашего компонента и последующего вызова метода. - person NechiK; 19.08.2017
comment
Я смог решить эту проблему, выполнив: element.controller('playerList'); - person Youness Houdass; 19.08.2017
comment
Тоже могло сработать. Но только у меня это не сработало в некоторых случаях - person NechiK; 19.08.2017

Я смог решить эту проблему, выполнив: element.controller('playerList');

 it('should render the text', function() {
    var component = element.controller('playerList');
    spyOn(component, 'removePlayer').and.callThrough();
    var title = element.find('h1');
    var deleteBtn = element[0].querySelector('button');
    expect(title.text()).toBe('Ce tableau contient ' + playersList.length + ' joueurs.');
    deleteBtn.click();
    expect(title.text()).toBe('Ce tableau contient ' + (playersList.length - 1) + ' joueurs.');
    expect(component.removePlayer).toHaveBeenCalled();
});
person Youness Houdass    schedule 19.08.2017