0

我有以下指令,它告訴我,是否我想要使用的圖像已成功或沒有加載:

return { 
    restrict: 'A', 
    scope: { 
     imageLoad: '@' 
    }, 
    link: function(scope, element, attrs) { 

     attrs.$observe('imageLoad', function (url) { 
      var deferred = $q.defer(), 
       image = new Image(); 

      image.onerror = function() { 
       deferred.resolve(false); 
      }; 

      image.onload = function() { 
       deferred.resolve(true); 
      }; 

      image.src = url; 
      return deferred.promise; 
     }); 

    } 
}; 

所有我然後要做的就是兩個簡單的測試,測試image.onerrorimage.onload但我似乎只是進入的誤差函數,這是我到目前爲止有:

compileDirective = function() { 
    var element = angular.element('<div data-image-load="http://placehold.it/350x150"></div>'); 
    $compile(element)(scope); 
    $rootScope.$digest(); 
    return element; 
}; 

beforeEach(inject(function (_$compile_, _$rootScope_) { 
    $compile = _$compile_; 
    $rootScope = _$rootScope_; 
    scope = $rootScope.$new(); 
})); 

it('should do something', function() { 
    var compiledElement, isolatedScope; 
    compiledElement = compileDirective(); 
    isolatedScope = compiledElement.isolateScope(); 
    expect(true).toBe(true); 
}); 

顯然這個測試通過,因爲它只是希望真的是不過,就覆蓋範圍而言,這是成立的他的onerror函數,所以我不知何故需要測試deferred.promise應該返回false。

所以最終一個問題的兩個部分,我如何得到deferred.resolve的結果呢?

其次我如何進入的onload功能?

我已經繞了一看,看到添加以下的一些建議:

element[0].setAttribute('imageLoad','http://placehold.it/350x150'); 
$compile(element)(scope); 
element.trigger('imageLoad'); 

和離開data-image-load=""空白,但沒有似乎存有任何僥倖,任何建議將是巨大的。

+0

這不涉及到你的問題,但有你使用'ATTRS什麼特殊原因$ observe'?現在你可以刪除它並用'scope.imageLoad'替換'url'。現在,傳遞給'$ observe'的匿名函數只返回承諾,但沒有人能夠查看結果。指令的要點是什麼?它應該如何使用? – tasseKATT

+0

@tasseKATT基本上,實際應用程序中的圖像路徑將是動態的,因此可能會更改,因此需要重新觸發。承諾確保它被加載,如果失敗我會提供一個後備圖像,我已經省略了上面例子中的一些代碼,在那裏我使用element.css(背景圖像)設置了一個後備圖像 – gardni

+0

因此,指令本身就是唯一一個對承諾的結果作出反應的人? – tasseKATT

回答

1

從你給什麼,你不應該需要承諾在所有。

即使你做到了,因爲承諾僅供內部使用,沒有人使用的結果,它應被視爲一個實現細節,你的測試不應該關心它。

讓我們說,你有以下指令:它使用

app.directive('imageLoad', function() { 
    return { 
    restrict: 'A', 
    scope: { 
     imageLoad: '@' 
    }, 
    link: function(scope, element, attrs) { 

     var fallback = 'http://placekitten.com/g/200/300'; 

     attrs.$observe('imageLoad', function(url) { 

     var image = new Image(); 

     image.onerror = function(e) { 

      setBackground(fallback); 
     }; 

     image.onload = function() { 

      setBackground(url); 
     }; 

     image.src = url; 
     }); 

     function setBackground(url) { 
     element.css({ 
      'background': 'url(' + url + ') repeat 0 0' 
     }); 
     } 
    } 
    }; 
}); 

演示:http://plnkr.co/edit/3B8t0ivDbqOWU2YxgrlB?p=preview

從外部的角度來看,該指令的目的是把元素的背景設置爲根據傳遞的URL是否正常工作,傳遞的URL或回退。

所以,你要測試的是:

  1. 傳遞的網址是工作 - 應使用通過URL作爲背景。
  2. 傳遞的url不起作用 - 應使用備用作爲背景。

這意味着您需要能夠控制圖像是否可以加載。

爲了防止在您的測試任何網絡流量我會建議使用數據URI,而不是網址。

例子:

var validImage = 'data:image/jpeg;base64, + (Valid data omitted)'; 
var invalidImage = 'data:image/jpeg;base64,'; 

完整的示例:

describe('myApp', function() { 

    var $compile, 
    $rootScope; 

    beforeEach(module('myApp')); 

    beforeEach(inject(function(_$compile_, _$rootScope_) { 
    $compile = _$compile_; 
    $rootScope = _$rootScope_; 
    })); 

    var validImage = 'data:image/jpeg;base64, + (Valid data omitted)'; 
    var invalidImage = 'data:image/jpeg;base64,'; 

    compileDirective = function(url) { 
    var element = angular.element('<div data-image-load="' + url + '"></div>'); 
    return $compile(element)($rootScope.$new()); 
    }; 

    it('should use correct background when image exists', function(done) { 

    var element = compileDirective(validImage); 

    $rootScope.$digest(); 

    setTimeout(function() { 

     var background = element.css('background'); 
     expect(background).toBe('url("' + validImage + '") 0px 0px repeat'); 

     done(); 

    }, 100); 
    }); 

    it('should use fallback background when image does not exist', function(done) { 

    var element = compileDirective(invalidImage); 

    $rootScope.$digest(); 

    setTimeout(function() { 

     var background = element.css('background'); 
     expect(background).toBe('url("http://placekitten.com/g/200/300") 0px 0px repeat'); 

     done(); 

    }, 100); 
    }); 
}); 

注意,由於圖像的加載是異步的,你需要添加在你的測試等待一下。

你可以閱讀更多關於如何使用茉莉花here完成。

演示:http://plnkr.co/edit/W2bvHih2PbkHFhhDNjrG?p=preview

+1

感謝您提供了這樣一個很好的答案,明確地花了很多時間來理解問題並找出解決方案,我擔心我的方法原本可能不正確,這個解決方案完美運行,我特別喜歡您對base64編碼的建議。 – gardni

+0

@gardni不客氣:) – tasseKATT