DEV Community

Cover image for Refactoring For jQuery
bob.ts
bob.ts

Posted on • Updated on

Refactoring For jQuery

Set Up

Recently, in some client code, I found a lot of jQuery usage. While working with them to build a better test suite, I started with some simple refactoring to make these functions more testable.

The initial code looked like this ...

const testableCode1 = {
  test: function() {
    return testableCode.runTest();
  },
  runTest: function() {
    var elements = $('.elements');
    return elements.length;
  }
};
Enter fullscreen mode Exit fullscreen mode

Initial Test Coverage

There were no initial tests. Since we wanted to do some refactoring, we wound up with a simple pattern to allow for refactoring ...

describe('pre-refactor', function() {
  it('test before refactor', function() {
    var itemToReturn = $('<div></div>');
    spyOn(window, '$').and.callFake(function(item) {
      if (item === '.elements') {
        return itemToReturn;
      }
    });

    var result = testableCode1.test();

    expect(result).toEqual(1);
  });
});
Enter fullscreen mode Exit fullscreen mode

Refactor

Now, with these tests in place, we can refactor the code with a level of confidence that the functionality will remain the same.

Here's the refactored testableCode code ...

const testableCode2 = {
  test: function() {
    var elements = $('.elements');
    return testableCode2.runTest(elements);
  },
  runTest: function(items) {
    return items.length;
  }
};
Enter fullscreen mode Exit fullscreen mode

Rework Tests

Given this refactor, the old test put into place should still pass and we can now write tests without the spyOn being used ...

describe('post-refactor', function() {
  it('test before refactor', function() {
    var itemToReturn = $('<div></div>');
    spyOn(window, '$').and.callFake(function(item) {
      if (item === '.elements') {
        return itemToReturn;
      }
    });

    var result = testableCode2.test();

    expect(result).toEqual(1);
  });

  it('test after refactor', function() {
    var itemToReturn = $('<div>');
    var result = testableCode2.runTest(itemToReturn);
    expect(result).toEqual(1);    
  });
});
Enter fullscreen mode Exit fullscreen mode

Conclusion

Now that the code has been refactored, the initial test could easily be removed, making the tests much cleaner and simpler to work with.

Top comments (3)

Collapse
 
amersikira profile image
Amer Sikira

I can see that a lot of people are saying that jQuery is no go. But honestly, I still tend to use it where ever I can. Am I going to Hell? :D

Collapse
 
rfornal profile image
bob.ts

Possibly ... I have heard the same conversations, but when I am prototyping, nothing's better.

Collapse
 
amersikira profile image
Amer Sikira

Yeah. I like it because it is easy to use, a lot of plugins, etc. There were some rumors that they' ll stop supporting and developing it, but as far as I know they did not.