Search code examples
coffeescriptstubbingsinonbuster.js

Sinon.JS stub for window.location.search


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.


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.