How do I declare a variable in a specific scope in coffeescript?

16,852

Solution 1

You are doing it the right way.

This is described in the CoffeeScript documentation. I wouldn't worry about the JS that it creates. Yes, it is a bit messy if you were to write it yourself, but this is one of the things that you have to live with when you use a re-writer like CoffeeScript.

You do, however, have a couple of options which are pretty nice.

You can put the variables in the current context if you wish (which happens to be your jasmine.Spec object for the curious, so it is a relatively safe and appropriate place to be putting variables... just don't overwrite existing vars in the context.):

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

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

You can also setup your own variable in which to store things

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

Solution 2

Your test could be written like the following:

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

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

Much cleaner syntax - without the need to make things global.

Share:
16,852
Kevin Peterson
Author by

Kevin Peterson

Continuous agile dev engineer ops at Wealthfront ninja monastery.

Updated on June 27, 2022

Comments

  • Kevin Peterson
    Kevin Peterson about 2 years

    I'm trying to write a jasmine test in coffeescript that uses a beforeEach block. This runs into a problem with coffeescript's variable scoping. Here's what I'd like to write:

    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'})
    

    This doesn't work, though, because the scope and $browser will get declared with var in the innermost scope. That is, once in the beforeEach and then again in the it block. I can force the variables to be declared in the right scope by initializing them, but this seems very strange:

    describe 'PhoneDetailCtrl', () ->
      $browser = {}
      scope = {}
      beforeEach () ->
        scope = angular.scope()
        $browser = scope.$service('$browser')
    
      it 'should fetch phone detail', () ->
        scope.params = {phoneId:'xyz'}
        ...
    

    This works, but the javascript it compiles to is actually

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

    where all I need is the line var $browser, ctrl, scope;. Can I write this more concisely in coffeescript?

  • Fluffy
    Fluffy over 11 years
    You can also use a = b = c = d = null for spare lines. The variables won't affect each other (as opposed to if you'd assign them to {})
  • StackExchange What The Heck
    StackExchange What The Heck almost 9 years
    You link's dead. I'm not sure if/where it is now, or I'd suggest an edit.