web-dev-qa-db-ja.com

coffeescriptの特定のスコープで変数を宣言するにはどうすればよいですか?

BeforeEachブロックを使用するコーヒースクリプトでジャスミンテストを記述しようとしています。これはcoffeescriptの変数スコープに関する問題にぶつかります。これが私が書きたいものです:

describe 'PhoneDetailCtrl', () ->
  beforeEach () ->
    scope = angular.scope()
    $browser = scope.$service('$browser')

  it 'should fetch phone detail', () ->
    scope.params = {phoneId:'xyz'}
    $browser.xhr.expectGET('phones/xyz.json').respond({name:'phone xyz'})
    ctrl = scope.$new(PhoneDetailCtrl)

    expect(ctrl.phone).toEqualData({})
    $browser.xhr.flush()

    expect(ctrl.phone).toEqualData({name:'phone xyz'})

ただし、これは機能しません。scopeおよび$browserは、最も内側のスコープでvarを使用して宣言されます。つまり、一度beforeEachに含まれ、次にitブロックに含まれます。変数を初期化することで、変数を正しいスコープで宣言することができますが、これは非常に奇妙に見えます。

describe 'PhoneDetailCtrl', () ->
  $browser = {}
  scope = {}
  beforeEach () ->
    scope = angular.scope()
    $browser = scope.$service('$browser')

  it 'should fetch phone detail', () ->
    scope.params = {phoneId:'xyz'}
    ...

これは機能しますが、コンパイルするJavaScriptは実際には

describe('PhoneListCtrl', function() {
  var $browser, ctrl, scope;
  $browser = {};
  ctrl = {};
  scope = {};

必要なのはvar $browser, ctrl, scope;。これをコーヒースクリプトでもっと簡潔に書くことはできますか?

38
Kevin Peterson

あなたはそれを正しい方法で行っています。

これは CoffeeScriptのドキュメント で説明されています。それが作成するJSについては心配しません。はい、自分で書くのは少し面倒ですが、これは、CoffeeScriptのようなリライターを使用するときに必要なものの1つです。

ただし、かなりいいオプションがいくつかあります。

必要に応じて、変数を現在のコンテキストに置くことができます(好奇心が強い人にとってはjasmine.Specオブジェクトです)。これは、変数を置くのに比較的安全で適切な場所です...上書きしないでください コンテキスト内の既存の変数 。):

describe 'PhoneDetailCtrl', () ->
  beforeEach () ->
    @scope = angular.scope()
    @$browser = @scope.$service('$browser')

it 'should fetch phone detail', () ->
  @scope.params = {phoneId:'xyz'}
  #... etc

物事を保存する独自の変数を設定することもできます

describe 'PhoneDetailCtrl', () ->
  setup = {}

  beforeEach () ->
    setup.scope = angular.scope()
    setup.$browser = setup.scope.$service('$browser')

  it 'should fetch phone detail', () ->
    setup.scope.params = {phoneId:'xyz'}
    #... etc
30
Brian Genisio

テストは次のように書くことができます:

describe "MyGame", ->
    mygame = null
    beforeEach inject (_MyGame_) ->
        mygame = _MyGame_

    it "should have two players", ->
        expect(mygame.opponents.length).toEqual 2

構文がより明確になりました-グローバル化する必要はありません。

10