Угловое тестирование DOM после обновления Factory

Хорошо, я пытаюсь проверить результат функции, которая обновляет DOM> У меня есть директива, которая загружает шаблон через URL-адрес. Затем контроллер вызывает фабричный метод для обновления таблицы html данными. У меня есть тесты, показывающие, что я могу получить все данные, которые хороши. но как я могу проверить, что обновления таблицы произошли?

Я использую NodeJS с Karma и Jasmine.

Я следил за учебными пособиями о том, как загружать шаблоны, и у меня это работает, я могу загружать и получать доступ к шаблонам в своем тесте в порядке.

но когда я запускаю метод для обновления таблицы, тесты терпят неудачу.

Я приведу уменьшенный пример того, что я пытаюсь сделать. Обратите внимание, это всего лишь демонстрационный код, а не рабочее приложение.

Шаблон.

<table><tr><td class="cell1"></td></tr></table>

Директива.

    dataTable.directive('dataTable', function () {
    return {
        restrict: 'E',
        templateUrl: 'path/to/template/dataTable.html'
    };
});

Контроллер

dataTable.controller('dataTableController', ['$scope', 'dataTableFactory',
                     function ($scope, dataTableFactory){        

    $scope.updateTable = function(){           
       dataTableFactory.loadData(); 
       // code to load data from dataTableFactory here! //          
       dataTableFactory.updateTable();
    }

}])

Фабрика

dataTable.factory('dataTableFactory',['$document',function($document){
    var _tableData;
    return(
            "tableData": _tableData,
            loadData: function(){
              // code to get data and populate _tableData.
            }
            updateTable: function(){
                $document.find('.cell1').append(this.tableData.data);
            }
    )
}])

Модульный тест

describe('dataTable Tests', function () {
    var scope, element, $compile, mDataTableFactory, controller, tableData, doc, factory;
    beforeEach(module('dataTable'));
    beforeEach(module('app.templates')); // setup via ng-html2js
    beforeEach(inject(function (_$rootScope_, _$compile_,_$controller_,_dataTableFactory_) {
        scope   = _$rootScope_.$new();
        doc = _$compile_('<flood-guidance></flood-guidance>')(scope);
        factory = _dataTableFactory_;
        controller = _$controller_('dataTableController', {
            $scope: scope,
            $element: doc,
            dataTableFactory: factory
        }); 
        scope.$digest();
    }));

    it("Template should contain the cell cell1", function(){
        expect(doc.find('.cell1').contents().length).toBe(0);
        expect(doc.find('.cell1').html()).toBeDefined();
    });
    // Passes fine, so I know the template loads ok.
    it('Should show data in cell1',function(){
        factory.tableData = {data: 'someData'};
        scope.updateTable();
        expect(doc.find('.cell1').contents().length).toBe(1);
        expect(doc.find('.cell1').html()).toBe('SomeData');
    });
  });
});

Тестовый выход

Ожидается, что 0 будет 1. Ожидается, что '' будет 'someData'.

Если я вставлю код updateTable в контроллер и вызову там функцию обновления, тест пройдет, но я бы хотел, чтобы это было на фабрике, как я могу сделать этот тест пройденным (приложение работает и работает, как и ожидалось, я просто не могу получить рабочий тест).

Я понимаю, что этот тип тестирования больше ориентирован на пользовательский интерфейс, а не на «модульное тестирование», но возможно ли это сделать?


person Status420    schedule 13.11.2014    source источник


Ответы (1)


Таким образом, updateTable не может найти изменения, выполненные factory.tableData. Я предполагаю, что проблема может быть связана с тем, как ваша фабрика предоставляет свойство _tableData. Не могли бы вы попробовать изменить свою фабрику следующим образом:

dataTable.factory('dataTableFactory',['$document',function($document){
    var _tableData;
    return(
            getTableData: function() { return _tableData; },
            setTableData: function(newVal) { _tableData = newVal; },
            loadData: function(){
              // code to get data and populate _tableData.
            }
            updateTable: function(){
                $document.find('.cell1').append(this.tableData.data);
            }
    )
}])

а затем, конечно, используйте установщик/геттер соответственно. Посмотрите, работает ли это таким образом.

Итак, я все еще не уверен, полностью ли я понял ваше намерение, но вот скрипка с моим рефакторинговым примером. http://jsfiddle.net/ene4jebb/1/

Прежде всего, фабрика не должна касаться DOM, это ответственность директив. Таким образом, моя доработка передает значение ячейки (свойство новой области видимости) в директиву, которая его отображает. Теперь, когда вы вызываете setTableData (который изменит _tableData.data) и поскольку в тестовой среде вы сами вызываете цикл $digest, директива автоматически перерисовывает новый материал. Контроллер остается тонким, насколько это возможно, таким образом, предоставляя фабрике только свойство области действия.

Как сказано, не уверен, что вы были после этого, но надеюсь, что это поможет. Если есть какие-либо вопросы, просто спросите.

person zewa666    schedule 13.11.2014
comment
Извините, возможно, недостаточно хорошо объяснил. Данные отображаются в ячейке таблицы нормально, например, если я запускаю приложение в обычном режиме (т.е. в браузере). В тесте он терпит неудачу, потому что я не могу получить обновленный DOM, я получаю исходный DOM без данных, добавленных в ячейку. Мне нужно знать, как протестировать DOM после его обновления с помощью updateTable. Мне нравится ваша идея с установкой и получением переменных, я все равно это реализую. - person Status420; 13.11.2014
comment
Я обновил свой ответ скрипкой. Все еще не уверен, что это то, что вам нужно, но пример с рефакторингом может помочь вам в вашем путешествии. - person zewa666; 13.11.2014
comment
Что ж, теперь с помощью метода set вы можете это сделать. Процесс установки Dom остается прежним, я думаю, что вы действительно хотите проверить, это само значение. Что касается нескольких ячеек, просто используйте ngrepeat внутри шаблона. - person zewa666; 13.11.2014
comment
Большое спасибо, я действительно волновался, что обновляю DOM не в том месте, но моя причина для этого (не указанная в примере из-за сложности) заключалась в том, что мне нужно оценить данные, прежде чем добавлять их. Кроме того, нужно заполнить 16 ячеек таблицы, изначально я не хотел использовать переменные в шаблоне, потому что думал, что это будет беспорядочно, сложно или плохо работает, но это может быть выходом. В моем «фактическом» коде фабричного метода updateTable проверяется 4 фрагмента данных, оценивается каждый из них перед добавлением html. Могу ли я выполнить оценку в контроллере до того, как директива обновит DOM? - person Status420; 13.11.2014
comment
В смысле правильного проектирования mvc контроллеры не несут ответственности за какую-либо бизнес-логику. Почему бы не перенести логику на фабрику и не оценить перед вызовом сеттера? - person zewa666; 13.11.2014