Testing a click event with Jasmine that appends a style sheet to the head
Asked Answered
A

3

5

jQuery

$(".theme-picker").click(function () {
      $('head').append('<link rel="stylesheet" href="" type="text/css" media="screen" id="theme_switcher"/>');
});

Jasmine

describe("style.switcher", function() {

beforeEach( function() {
    jasmine.getFixtures().set(
        '<head></head>' +
        '<div class="switcher">' +
          '<a class="theme-picker" title="theme-picker"></a>' +
          '<a class="folder-picker" title="folder-picker"></a>' +
          '<a class="font-picker" title="font-picker"></a>' +
          '<a class="color-picker" title="color-picker"></a>' +
        '</div>' );
  });

it("loads themes switcher link in head", function() {
  $('.theme-picker').trigger('click');
  expect( $('head') ).toContain("theme_switcher");
});
});

I am new to jasmine and the test is currently failing. I am unsure if it is the fixture, the trigger event or something else entirely.

Alduino answered 30/5, 2012 at 20:28 Comment(0)
C
7

I think the chosen answer (even though it's by the OP!) is misleading and incorrect. I'm not sure why it would be "poor form" to test the effect that a piece of JavaScript has on some targeted HTML. Often that's the only output that you can use to verify whether a method works.

The test that's used as an example doesn't actually prove anything: of course click was triggered, you just triggered it! What you want to do is prove something that follows from that click, e.g. a change in a DOM or other data structure, which was the original (IMO correct) instinct.

What you want is to use an asynchronous test to wait for a change in the DOM and then give up, similar to the way the Ruby library Capybara works:

it('loads themes switcher link in head', function() {
  $('.theme-picker').trigger('click');

  waitsFor(function() {
    return $('head').contains('theme_switcher');
  }, 'theme switcher never loaded', 10000);
});
Catalectic answered 25/7, 2012 at 5:31 Comment(0)
A
1

Research has shown it is in poor form to test page specific elements.

My current test (passing) is as follows:

describe("zen switcher", function() {

beforeEach( function() {
  loadFixtures('zen_switcher.html');
  spyOnEvent($('.theme-picker'), 'click');
});

it("clicks the .theme-picker", function() {
  $('.theme-picker').click();
  expect('click').toHaveBeenTriggeredOn($('.theme-picker'));
});
});
Alduino answered 1/6, 2012 at 21:24 Comment(0)
A
0

theme_switcher is the id of your link. toContain takes a selector, i.e. you should be writing toContain('#theme_switcher').

Also make sure you are appending in the sandbox and also checking the head of the sandbox, not your document's.

EDIT:

I assume you use jasmine-jquery

Aggrandize answered 1/6, 2012 at 19:0 Comment(4)
I was not aware that toContain() could take a CSS selector as an argument. Do you have a reference you could link to?Science
I was curious about this so I did some searching. Under the hood, toContain() calls jasmine.Env.prototype.contains_() which is defined here. I don't see anything that would indicate that it will accept a CSS selector, but I'd loved to be proven wrong!Science
How do you check the head of the sandbox? I think that the only head that will show up in the test is the document's. sandbox(); returns <div id="sandbox"></div>Alduino
I assume you jasmine-jquery which totally make sense in your case. Have a look at the link, you'll notice toContain takes a jQuery selector. You might have a head in your html outside the sandbox. $('head') will return both.Aggrandize

© 2022 - 2024 — McMap. All rights reserved.