Question

I am trying to test a simple function that makes a call to window.location.search. I'm trying to understand how to stub this call so that I can return a url of my choosing.

function:

getParameterByName: (name) =>    
  name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]")
  regexS = "[\\?&]" + name + "=([^&#]*)"
  regex = new RegExp(regexS)    
  results = regex.exec(window.location.search) //Stub call to window.location.search
  if(results == null)
    return ""
  else
    return decodeURIComponent(results[1].replace(/\+/g, " "))

Test case:

describe "Data tests", () ->
  it "Should parse parameter from url", () ->        
    data = new Data()

    console.log("search string: " + window.location.search) //prints "search string:"
    window.location.search = "myUrl"
    console.log("search string: " + window.location.search) //prints "search string:"
    console.log(data.getParameterByName('varName'))

    expect(true).toBe(true)

My original attempt was to return a value directly like so:

sinon.stub(window.location.search).returns("myUrl")

This, of course, doesn't work. I don't think I'm specifying the stub correctly, but it shows my intent.

Any ideas on how to solve this would be greatly appreciated.

Was it helpful?

Solution

So, as mentioned before, you can't mock window.location directly. Nor did the mylib.search wrapper idea work with my situation. So, what I did was break out my call to window.location.search into its own function. My new class looks like so:

getParameterByName: (name) =>
  console.log("name: #{name}")
  name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]")
  regexS = "[\\?&]" + name + "=([^&#]*)"
  regex = new RegExp(regexS)
  results = regex.exec(@getWindowLocationSearch())
  if(results == null)
    return ""
  else
    return decodeURIComponent(results[1].replace(/\+/g, " "))

getWindowLocationSearch:() =>
  window.location.search

Then in my test case, I replace the function with my test code like so:

describe "Data tests", () ->
  it "Should parse parameter from localhost url", () ->
    goodUrl = "http://localhost:3333/?token=val1"

    Data::getWindowLocationSearch = () -> return goodUrl
    unit = new Data()
    result = unit.getParameterByName("token")

    expect(result).toBe("val1")

For those who don't read Coffeescript, the equivalent javascript code is listed below:

it("Should parse parameter from localhost url", function() {
  var goodUrl, result, unit;
  goodUrl = "http://localhost:3333/?token=val1";
  Data.prototype.getWindowLocationSearch = function() {
    return goodUrl;
  };
  unit = new Data();
  result = unit.getParameterByName("token");
  expect(result).toBe("val1");
  return expect(true).toBe(true);
});

As is my usual experience with Javascript. The working solution was not nearly as painful as the journey to get there. Thank you very much for your comments and contributions.

OTHER TIPS

UPDATE: window.location, it seems, is a bit of a special case, see this discussion: https://groups.google.com/forum/?fromgroups#!topic/sinonjs/MMYrwKIZNUU%5B1-25%5D

The easiest way to solve this problem is to write a wrapper function around window.location, and stub that:

mylib.search = function (url) {
  window.location.search = url;
};

And in your test:

sinon.stub(mylib, 'search').returns("myUrl")

ORIGINAL ANSWER:

Try this:

sinon.stub(window.location, 'search').returns("myUrl")
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top