Category Archives: Javascript

Vue testing with Jest: Mock window.location

The bottom line is that you can not mock window.location, BUT you can delete it and create your own to use in test. I will here show one example of how this can be achived:

describe('methodUnderTest', () => {
  // Save current windows.location
  const oldWindowLocation = window.location;
  // Some mocked value
  const mockedUrl = 'https://blog.niklasottosson.com';

  beforeEach(() => {
    // Remove windows.location so that we can create a new
    delete window.location;

    // Create a new mutable window.location
    window.location = Object.defineProperties(
      {},
       {   // copy all properties from the old window.location
        ...Object.getOwnPropertyDescriptors(oldWindowLocation),
        // Start mocking...
        assign: {
           configurable: true,
           value: jest.fn()
        },
        href: {
            configurable: true,
            value: mockedUrl
        }
     );
  });

  afterEach(() => {
    // Restore window.location
    window.location = oldWindowLocation;
  });

  // Start creating your tests...
  it('should...', () => {
    ...
  } 

Tested on OSX 10.15.7, Vue v2.6.12 and Jest v26.0.14

My time number format knockout binding

I made this binding so that I could correct the time number format written by a user (hh:mm). A way to make inputing time values easier. The binding will create time strings from one, two, three and four values. It vill also correct any mistyped characters in between hour and minutes

ko.bindingHandlers.timebox = {
  init: function(element, valueAccessor) {
    var allNumbers = /^\d{4}$/;
    var oneNumber = /^\d$/;
    var twoNumbers = /^\d{2}$/;
    var threeNumbers = /^\d{3}$/;
    var correct = /^\d{2}.\d{2}$/;
    var observable = valueAccessor();
    var formatted = ko.computed({
      read: function (key) {
        return observable();
      },
      write: function (value) {
        if(correct.test(value)){
          value = value.substring(0,2) + ':' + value.substring(3);
        }
        else if(allNumbers.test(value)) {
          value = value.substring(0,2) + ':' + value.substring(2);
        }
        else if(threeNumbers.test(value)) {
          value = '0' + value.substring(0,1) + ':' + value.substring(1);
        }
        else if(oneNumber.test(value)) {
          value = '0' + value + ':00';
        }
        else if(twoNumbers.test(value)) {
          value = value + ':00';
        }
        else {
          alert("Wrong time format specified (hh:mm)");
          value = '';
        }
        observable(value); // Write to underlying storage 
      },
      disposeWhenNodeIsRemoved: element                
    });
 
    //apply the actual value binding with our new computed
    ko.applyBindingsToNode(element, { value: formatted });
  }        
};

Using it is really easy. Just replace ‘value’ with ‘timebox’ like this:

<input id="my_id" type="text" data-bind="timebox:my_observable"/>

Tested on OSX 10.7.5, Chrome 37.0.2062.94, KnockoutJS 3.1.0

Filter a table dynamically using JQuery

Say you have a table that you would like to filter depending on a search word/s. Before JQuery this was quite a cumbersome task to solve this with javascript. Thanks to JQuery we can today with a few simple lines enable any table to be filtered. Let’s jump straight into it:

Here is the HTML for the table and search input field

<input id="sq" type="text">
 
<table id="ot">
  <thead>
    <tr>
      <th>Col 1</th><th>Col 2</th><th>Col 3</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Value 1</td><td>Value 2</td><td>Value 3</td>
    </tr>
    <tr>
      <td>Value 4</td><td>Value 5</td><td>Value 6</td>
    </tr>;
    <tr>;
      <td>;Value 7</td><td>Value 8</td><td>Value 9</td>
    </tr>
  </tbody>
</table>

…and here is the code

$("#sq").keyup(function(){
  if($("#sq").val().length > 2){ 	
 
    $("#ot tr").not(":first").not(":contains("+$("#sq").val()+")").hide();
  }
  else {
    $("#ot tr").show();
  }
});

Lets explain a little:

  • We use the keyup function to trigger the filter event. It will fire every time we let go of a button but the search event will only happen if the search string is longer than 2 letters
  • The magic happens in the next line where we first get all rows (<tr>), except the first (which is the table header). We then find all rows NOT containing our search string and hide them using the JQuery hide() function. This way only the ones that actually contain our search string will be visible
  • Lastly we show every row if the search string is shorter than 3 letters

And that is it!

Tested on JQuery 1.9.1 and Chrome 34.0.1847.131