AngularJS директивасының сынағынан басу оқиғасын қалай имитациялауға болады?

Мен ng-directive-testing пішімін қолданып көрдім Мен жазған директиваға репо. Директива, негізінен, пайдаланушы элементті нұқыған кезде қабаттасады. Директива (қарапайым):

mod.directive('uiCopyLinkDialog', function(){
    return {
        restrict: 'A',
        link: function(scope, element, attrs) {
            var $elm = angular.element(element);
            element.bind('click', function(event) {
                $elm.addClass('test');
            });
        }
    };
});

Мен жазған тестім мынаған ұқсайды:

describe('pre-compiled link', function() {

    beforeEach(mocks.inject(function($compile, $rootScope) {
        scope = $rootScope;
        element = angular.element('');
        $compile(element)(scope);
        scope.$digest();
    }));

    it("should change the class when clicked", function() {
        element.click();//this returns "'undefined' is not a function"
        element[0].click();//so does this
        $(elm).click();//this uses jQuery and doesn't *seem* to fail
        waits(500);//hack to see if it was a race condition
        expect(elm.className).toContain('test');//always fails
    });

});

Тестте сілтемедегі click() оқиғасын іске қосудың бірнеше әдісін көруге болады, олардың көпшілігі undefined қатесін береді.

Маған қандай қателесіп жатқанын біреу айта алады ма? Бұл мысалдарды оқып үйрену дұрыс синтаксис сияқты, бірақ менің сынақ жүгірушім (Кармен арқылы Grunt) доп ойнағысы келмейді.

48
Спасибо: бұл шын мәнінде бұл сынақтарды PhantomJS-те іске қосқан қате деп ұқсайды - Chrome-дағы тесттерді іске қосқан кезде click() оқиғаларын дұрыс өртеді. Қызық!
қосылды автор Matt Andrews, көзі
Сіз ID идентификаторын беруді және Id: angular.element ('span [id = «theSpan»] «) негізінде таңдауды қалауыңыз мүмкін. Сонымен қатар сіз диалогты айтып тұрғанымды көргеннен кейін ... jQuery тілқатысу терезесін пайдаланасыз ба? егер болса; тілқатысу терезесі ашылғанда осы диалогтың сыртында ешқандай нәрседе басу оқиғасын іске қосудан бас тартасыз. Шешім тілқатысу терезесі жабылғаннан кейін оқиғаны іске қосу, содан кейін басу оқиғасын іске қосу.
қосылды автор Jeff Dalley, көзі

6 жауаптар

JQLite-тің бөлігі болып табылатын triggerHandler бағдарламасын пайдалануға болады.

Мен бұл директиваға басу оқиғасын іске қосу үшін қолданамын ...

element = angular.element("<div myDirective-on='click'></div>");
compiled = $compile(element)($rootScope);
compiled.triggerHandler('click');

Full example available on this blog post: http://sravi-kiran.blogspot.co.nz/2013/12/TriggeringEventsInAngularJsDirectiveTests.html

55
қосылды
Тамаша! Бірақ мен $ compile қадамын қажет етпедім.
қосылды автор Darwin Tech, көзі
Бұл жауапты сүйемін, себебі ол JQlite пайдаланады !!!!
қосылды автор Chris Story, көзі
Бұл менің таңдаған шешімім де, PhantomJS-мен жақсы жұмыс істейді. Менің жағдайымда элементін іске қосылдым
қосылды автор Dinis Cruz, көзі
Қызықтысы, сенің еркелетің жұмыс істемейді. Менде ұқсас мәселе бар мұнда бірақ бұл шешім оны толықтай шешпейді. Мүмкін сіз мәселені байқай аласыз ба?
қосылды автор miphe, көзі

Мәселен, бұл PhantomJS-те проблема болды: элементте әрекет ететін кейбір оқиғалар элементтердің ешқандай құжатта болмаған кезде, бірақ жадыда (бұл менің теориям). Осыған айналысу үшін мен осы функцияны қолдануға тура келді click оқиғалар элементтерінде:

define(function() {
    return {
        click: function (el) {
            var ev = document.createEvent("MouseEvent");
            ev.initMouseEvent(
                "click",
                true /* bubble */, true /* cancelable */,
                window, null,
                0, 0, 0, 0, /* coordinates */
                false, false, false, false, /* modifier keys */
                0 /*left*/, null
            );
            el.dispatchEvent(ev);
        }
    };
});

Бұл басқа да қиындықтарға қарамастан жұмыс істеді: Мен input форматы бар екенін қамтамасыз ететін тест жазуды қаладым, бірақ PhantomJS көмегімен бұл мәнді алу мүмкін болмады, себебі, менің болжауымша, браузер жасай алмайды экрандық көрініс болмаса, бір нәрсе шоғырланған. Мұны қажет ететін кез келген адам CasperJS-ді қарап шығуы мүмкін, ол кейбір талаптарға қарапайым API ұсынады.

18
қосылды
Сіз бұл функцияны қалай анықтайсыз? Мен бұл жұмысқа жете алмаймын. Мен мұндай функцияларды бұрынғы блокта анықтадым, бірақ ол ештеңе істемейді.
қосылды автор Andresch Serj, көзі
Мен енгізген , және mouse.click (element) деп аталатын жеке файлда.
қосылды автор Matt Andrews, көзі
@ViktorMolokostov өкінішті, бұл мәселе екі жыл бұрын жасалды және мен бұл кодты/техниканы көрмегендіктен ...!
қосылды автор Matt Andrews, көзі
element.click() мен үшін Firefox-де жұмыс істемеді. Бұл үзінді Chrome мен Firefox бағдарламаларында да жасалды. Мэтт мырза!
қосылды автор Narita, көзі
Сыналарымда көпіршігі шын мәніне орнатылса да, көпіршігі болмайды. Сіз осындай проблеманы бастан кешірдіңіз бе?
қосылды автор Viktor Molokostov, көзі
@MattAndrews, бәрібір жауап үшін рахмет. Btw, $ (el) .click() мен үшін жұмыс істеді.
қосылды автор Viktor Molokostov, көзі

Міне, менің шешімім - элементті шынымен органға қосу. Себебі түпкі мәселе - бұл фантом Джс жадыдағы элементтерге арналған оқиғаларды өрттемейтін болса, оқиғалардың шынайы болуы үшін әрбір элементті қосу оңайырақ көрінді.

afterEach(function(){
    $('body').empty();
});

it('should do something when clicked', function(){
    element = $compile('<div my-directive></div>')($scope);
    $('body').append(element);

   //fire all the watches, so the scope expressions will be evaluated
    $rootScope.$digest();

    $(element).find('.my-input').click();
});
4
қосылды
Хм, мен қарадым, бірақ jsbin маған жақсы көрінеді, тек жіберілген үтірде қате болып көрінген жағдайдан басқа. Сіз jQuery және оның клик әдісін пайдалануды қоса көрдіңіз бе? Айырмашылық болуы мүмкін. Сондай-ақ, егер оны жұмыс істей алмасаңыз, бұрыштың triggerHandler әдісін пайдалансаңыз, тыңдаушыларды элементке қолмен өртеуге болады.
қосылды автор frodo2975, көзі
Мен бұл тәсілді қолдандым, бірақ оны жұмыс істей алмаймын. Осындай мейірімді болуға және осы қалтаға қарап шығуға болады: jsbin.com/womored/edit?js, шығыс
қосылды автор Gerome Bochmann, көзі
$ ('body') орнына angular.element ('body') -ді қолдануға болады. Егер сіз jQuery пайдаланбасаңыз, оның орнына $ document енгізіңіз және оның орнына $ document.find ('body') пайдаланыңыз.
қосылды автор Gerome Bochmann, көзі

Мен де осыған байланысты қиындықтарға тап болдым. click() сияқты кез-келген элемент үшін PhantomJS-мен жұмыс істемейтін сияқты көрінеді. Ол әрдайым анықталмайды.

Шын мәнінде нағыз клик ретінде жақсы болмаса да, сіз ng-нұқудағы директиваның функциясына оның оқшауланған ауқымын басу арқылы имитациялауға болады:

var element = $compile('Click me')(scope);
var isolateScope = element.isolateScope();
isolateScope.myfunc();
scope.$digest();

/* check that things changed ... */
3
қосылды

<�Код> бұрыштық-сценарийді қосу және одан кейін browserTrigger (элемент, «нұқу») пайдалану туралы қалай хабарлауға болады?

1
қосылды

burular-test-runner кітапханасын пайдалана аласыз және сынақ келесідей болады:

const testRunner = require('angular-test-runner');

describe('directive',() => {
    let app;
    const {expectElement, click} = testRunner.actions;

    beforeEach(() => {
        app = testRunner.app(['mod']);
    });

    it("should add class when clicked", function() {
        const html = app.runHtml('');

        html.perform(
            click.in('.foo')
        );

        html.verify(
            expectElement('.foo').toHaveClass('test')
        );
    });

});
0
қосылды