QUnit + coffeescript scope
Asked Answered
D

2

6

In Javascript polluting the global namespace is generally regarded as a bad thing. This is why Coffeescript wraps all of your Javascript in a (function() {}).call(this); wrapper.

However, I've begun writing QUnit tests for my Coffeescript code, and QUnit complains that it can't find my functions.

1. Died on test #1: getGoodNamePart is not defined
getGoodNamePart is not defined at Object.<anonymous> (file:///Users/kevin/Documents/docs/code/chrome/tests.js:2:10) at Object.run 

I'd like to test the variables without polluting the global namespace. What's a good way to do this?

Here's the generated Javascript I want to test:

(function() {
getGoodNamePart = function(str) {
    if (str.charAt(0) === '"') {
      str.replace(/" <[^>]+>$"/g, "");
      str.replace(/"/g, "");
      return str;
    } else if (str.charAt(0) === '<') {
      str.replace(/<|>/g, "");
      return str;
    } else {
      return str;
    }
  };
}).call(this);

and my test.js file is:

test('getGoodNamePart()', function() {
  equals(getGoodNamePart("\"Kev Burke\" <[email protected]>"), "Kev Burke", "\"name\" <email> works");
  equals(getGoodNamePart("", "", "empty string works"));
  equals(getGoodNamePart("[email protected]", "[email protected]", "raw email works"));
  return equals(getGoodNamePart("<[email protected]>", "[email protected]", "email inside carets -> carets get stripped"));
});

Thanks, Kevin

Dela answered 24/6, 2011 at 23:23 Comment(2)
Some example code would be helpful.Demilune
Hi Aaron, I added an example.Dela
G
6

So, you say you want to test getGoodNamePart without polluting the global namespace. But, CoffeeScript automatically modularizes each file (with good reason—see my answer here), which means that the only way to access functions across files is to attach them to some global object. (I'm assuming that we're talking about the browser here, not a CommonJS environment, such as Node.js, where you'd use exports.)

That gives you three options:

  1. Attach getGoodNamePart to window. This is easiest, since the only change needed is prefixing getGoodNamePart with window. (or just @), but of course this maximizes namespace pollution.
  2. Attach getGoodNamePart to something else that's already attached to window or global.
  3. Move your tests inside of the same file as getGoodNamePart (an unusual practice in the JS world, but one worth considering, as it keeps the global namespace untouched and lets you easily go between your code and your tests).

Let's say that you want to go with #2, exporting functions like getGoodNamePart purely for testing. Call them "test targets." At the top of each file with a test target, add

window.testTargets ?= {}

and when you define getGoodNamePart, write

testTargets.getGoodNamePart = getGoodNamePart = (str) ->
  ...

Then at the top of your QUnit test suite, write

{getGoodNamePart} = testTargets

to get the function.

Gaiety answered 25/6, 2011 at 19:37 Comment(0)
L
2

I compile the coffee file with the --bare flag, for testing purpose

$ coffee -c -b your_file

this doesn't modularize compiled code

Lechner answered 16/7, 2011 at 21:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.