Как мне объявить переменную в определенной области видимости в coffeescript? - PullRequest
38 голосов
/ 04 ноября 2011

Я пытаюсь написать тест на жасмин в 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;.Могу ли я написать это более кратко в coffeescript?

Ответы [ 2 ]

30 голосов
/ 04 ноября 2011

Вы делаете это правильно.

Это описано в документации CoffeeScript . Я не буду беспокоиться о JS, который он создает. Да, если вы пишете это самостоятельно, это немного запутанно, но это одна из тех вещей, с которой вам придется жить, когда вы используете переписчик, такой как CoffeeScript.

У вас, однако, есть несколько вариантов, которые довольно хороши.

Вы можете поместить переменные в текущий контекст, если хотите (который является вашим объектом 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
10 голосов
/ 16 августа 2012

Ваш тест может быть записан так:

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

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

Более чистый синтаксис - без необходимости делать вещи глобальными.

...