Skip to content

Commit 5c2a074

Browse files
committed
a bit less weird unit tests
1 parent 31d725f commit 5c2a074

File tree

3 files changed

+126
-75
lines changed

3 files changed

+126
-75
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
"copy-webpack-plugin": "^4.0.1",
1919
"jasmine": "^2.5.3",
2020
"jsdom": "^9.12.0",
21+
"proxyquire": "^1.8.0",
2122
"webpack": "^2.2.1"
2223
},
2324
"dependencies": {

spec/fixed-footnotes-spec.js

Lines changed: 105 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,104 +1,147 @@
1-
var footnotes = require('../src/fixed-footnotes');
1+
var proxyquire = require('proxyquire');
2+
var utilStub = {};
3+
var footnotes = proxyquire('../src/fixed-footnotes', { "./util": utilStub });
24
var jsdom = require("jsdom");
35

4-
describe("fixed-footnotes", function() {
6+
describe("fixed-footnotes.constructor", function() {
57

6-
it("should work with no argument", function(done) {
8+
it("should create a container as the last node of body", function(done) {
79
jsdom.env("<body></body>", ["http://code.jquery.com/jquery.js"], function(err, w) {
810
global.window = w;
9-
var ffn = footnotes();
11+
footnotes();
12+
expect(w.$("body > *:last").hasClass("fixed-footnotes-container")).toBe(true);
13+
done();
14+
});
15+
});
16+
17+
it("should use the window passed as parameter", function(done) {
18+
jsdom.env("<body></body>", ["http://code.jquery.com/jquery.js"], function(err, w) {
19+
footnotes({}, w);
1020
expect(w.$(".fixed-footnotes-container").length).toBe(1);
1121
done();
1222
});
1323
});
1424

15-
it("should properly override default options", function(done) {
16-
jsdom.env("<body></body>", function(err, w) {
17-
var ffn = footnotes({ referencesSelector: "test" }, w);
18-
expect(ffn.options.referencesSelector).toBe("test");
19-
expect(ffn.defaultOptions.referencesSelector).toBe(".reference");
25+
it("should display a note if its reference is visible and the original note isn't", function(done) {
26+
jsdom.env("<body><p class='reference' href='#note'>reference</p><p id='note'>note</p></body>", ["http://code.jquery.com/jquery.js"], function(err, w) {
27+
spyOn(utilStub, "isElementInViewport").and.returnValues(true, false); // reference visible, note invisible
28+
footnotes({}, w);
29+
expect(w.$(".fixed-footnotes-note").length).toBe(1);
2030
done();
2131
});
2232
});
2333

24-
it("should create a container as the last node of body", function(done) {
25-
jsdom.env("<body><div></div></body>", ["http://code.jquery.com/jquery.js"],
26-
function(err, w) {
27-
var ffn = footnotes({}, w);
28-
expect(w.$("body > *:last").hasClass("fixed-footnotes-container")).toBe(true);
34+
it("shouldn't display a note if its reference is not visible", function(done) {
35+
jsdom.env("<body><p class='reference' href='#note'>reference</p><p id='note'>note</p></body>", ["http://code.jquery.com/jquery.js"], function(err, w) {
36+
spyOn(utilStub, "isElementInViewport").and.returnValues(false); // reference invisible
37+
footnotes({}, w);
38+
expect(w.$(".fixed-footnotes-note").length).toBe(0);
2939
done();
3040
});
3141
});
3242

33-
it("should create the container properly with the options provided", function(done) {
34-
jsdom.env("<body><div id='super'></div></body>", ["http://code.jquery.com/jquery.js"],
35-
function(err, w) {
36-
var ffn = footnotes({
37-
fixedContainerLocation: "#super",
38-
fixedContainerId: "myId",
39-
fixedContainerClass: "myClass"
40-
}, w);
41-
var $container = w.$("#super > *:last");
42-
expect($container.attr("id")).toBe("myId");
43-
expect($container.hasClass("myClass")).toBe(true);
43+
it("shouldn't display a note if its original note is visible", function(done) {
44+
jsdom.env("<body><p class='reference' href='#note'>reference</p><p id='note'>note</p></body>", ["http://code.jquery.com/jquery.js"], function(err, w) {
45+
spyOn(utilStub, "isElementInViewport").and.returnValues(true, true); // reference visible, note visible
46+
footnotes({}, w);
47+
expect(w.$(".fixed-footnotes-note").length).toBe(0);
4448
done();
4549
});
4650
});
4751

48-
it("should find a note given its reference", function(done) {
49-
jsdom.env("<body><p class='footnote' href='#note'>reference</p><p id='note'>note</p></body>",
50-
["http://code.jquery.com/jquery.js"],
51-
function(err, w) {
52-
global.window = w;
53-
var ffn = footnotes({}, w);
54-
var note = ffn._getNoteFromRef(w.$(".footnote")[0])
55-
expect(note.id).toBe("note");
52+
it("should take the options into account", function(done) {
53+
jsdom.env("<body><p class='myReference' href='#note'>reference</p><p id='note'>note</p><div id='myParent'></div></body>", ["http://code.jquery.com/jquery.js"], function(err, w) {
54+
spyOn(utilStub, "isElementInViewport").and.returnValues(true, false); // reference visible, note invisible
55+
footnotes({
56+
referencesSelector: ".myReference",
57+
fixedContainerLocation: "#myParent",
58+
fixedContainerId: "myContainerId",
59+
fixedContainerClass: "myContainerClass",
60+
footnoteClass: "myFootnoteClass",
61+
transformNote: function(elem) {
62+
elem.className += " addedClass";
63+
return elem;
64+
}
65+
}, w);
66+
expect(w.$("#myParent > #myContainerId").length).toBe(1);
67+
expect(w.$("#myContainerId").hasClass("myContainerClass")).toBe(true);
68+
expect(w.$(".myFootnoteClass").length).toBe(1);
69+
expect(w.$(".addedClass").length).toBe(1);
5670
done();
5771
});
5872
});
5973

60-
it("should return null if the note cant be found", function(done) {
61-
jsdom.env("<body><p class='footnote' href='#note'>reference</p></body>",
62-
["http://code.jquery.com/jquery.js"],
63-
function(err, w) {
64-
global.window = w;
65-
var ffn = footnotes({}, w);
66-
var note = ffn._getNoteFromRef(w.$(".footnote")[0])
67-
expect(note).toBe(null);
74+
it("shouldn't display a note if we can't find it", function(done) {
75+
jsdom.env("<body><p class='reference' href='#note'>reference</p></body>", ["http://code.jquery.com/jquery.js"], function(err, w) {
76+
spyOn(utilStub, "isElementInViewport").and.returnValues(true, false); // reference visible, note invisible
77+
footnotes({}, w);
78+
expect(w.$(".fixed-footnotes-note").length).toBe(0);
6879
done();
6980
});
7081
});
7182

72-
it("should add a note to the container", function(done) {
73-
jsdom.env("<body><p class='footnote' href='#note'>reference</p><p id='note'>note</p></body>",
74-
["http://code.jquery.com/jquery.js"],
75-
function(err, w) {
76-
global.window = w;
83+
});
84+
85+
describe("fixed-footnotes.stop", function() {
86+
87+
it("should remove the footnotes container and all its notes", function(done) {
88+
jsdom.env("<body><p class='reference' href='#note'>reference</p><p id='note'>note</p></body>", ["http://code.jquery.com/jquery.js"], function(err, w) {
89+
spyOn(utilStub, "isElementInViewport").and.returnValues(true, false); // reference visible, note invisible
7790
var ffn = footnotes({}, w);
78-
ffn._displayNote(w.$("#note")[0])
91+
expect(w.$(".fixed-footnotes-container").length).toBe(1);
7992
expect(w.$(".fixed-footnotes-note").length).toBe(1);
93+
ffn.stop();
94+
expect(w.$(".fixed-footnotes-container").length).toBe(0);
95+
expect(w.$(".fixed-footnotes-note").length).toBe(0);
8096
done();
8197
});
8298
});
8399

84-
it("should add the note properly with the options", function(done) {
85-
jsdom.env("<body><p class='footnote' href='#note'>reference</p><p id='note'>note</p></body>",
86-
["http://code.jquery.com/jquery.js"],
87-
function(err, w) {
88-
global.window = w;
89-
var ffn = footnotes({
90-
footnoteClass: "fixed-footnotes-note anotherClass",
91-
transformNote: function(elem) {
92-
w.$(elem).text(w.$(elem).text().toUpperCase());
93-
return elem;
94-
}
95-
}, w);
96-
ffn._displayNote(w.$("#note")[0])
100+
});
101+
102+
describe("fixed-footnotes.refresh", function() {
103+
104+
it("should display a note if a previously hidden reference is now visible", function(done) {
105+
jsdom.env("<body><p class='reference' href='#note'>reference</p><p id='note'>note</p></body>", ["http://code.jquery.com/jquery.js"], function(err, w) {
106+
spyOn(utilStub, "isElementInViewport").and.returnValues(false, // reference invisible
107+
true, false); // reference visible, note invisible
108+
var ffn = footnotes({}, w);
109+
expect(w.$(".fixed-footnotes-note").length).toBe(0);
110+
ffn.refresh();
97111
expect(w.$(".fixed-footnotes-note").length).toBe(1);
98-
expect(w.$(".fixed-footnotes-note").hasClass("anotherClass")).toBe(true);
99-
expect(w.$(".fixed-footnotes-note").text()).toBe("NOTE");
100112
done();
101113
});
102114
});
103115

104116
});
117+
118+
describe("fixed-footnotes.addRefreshListener", function() {
119+
120+
it("should add a function executed on refresh", function(done) {
121+
jsdom.env("<body></body>", ["http://code.jquery.com/jquery.js"], function(err, w) {
122+
var ffn = footnotes({}, w);
123+
ffn.addRefreshListener(done);
124+
ffn.refresh();
125+
});
126+
});
127+
128+
});
129+
130+
describe("fixed-footnotes.removeRefreshListener", function() {
131+
132+
it("should remove a function from the listener list", function(done) {
133+
jsdom.env("<body></body>", ["http://code.jquery.com/jquery.js"], function(err, w) {
134+
var someObj = { someFunc: () => false };
135+
spyOn(someObj, "someFunc");
136+
var ffn = footnotes({}, w);
137+
ffn.addRefreshListener(someObj.someFunc);
138+
ffn.removeRefreshListener(someObj.someFunc);
139+
ffn.refresh();
140+
setTimeout(function() {
141+
expect(someObj.someFunc).not.toHaveBeenCalled();
142+
done();
143+
}, 20);
144+
});
145+
});
146+
147+
});

src/fixed-footnotes.js

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ var FixedFootnotes = function(options, w) {
1919
this._eventListener = throttle(this.refresh.bind(this), 200);
2020
this._window.addEventListener("scroll", this._eventListener);
2121
this._window.addEventListener("resize", this._eventListener);
22-
this.refresh();
22+
this._refreshView();
2323
}
2424

2525
/*
@@ -58,18 +58,7 @@ FixedFootnotes.prototype.stop = function() {
5858
* Refresh the view.
5959
*/
6060
FixedFootnotes.prototype.refresh = function() {
61-
var self = this;
62-
util.emptyElement(this._fixedContainerList);
63-
this._fixedContainer.className = this.options.fixedContainerClass + " empty";
64-
this._getReferences().forEach(function(reference) {
65-
var note = self._getNoteFromRef(reference);
66-
if (!note) return;
67-
if (util.isElementInViewport(reference, self._window) && !util.isElementInViewport(note, self._window)) {
68-
self._displayNote(note);
69-
self._fixedContainer.className = self.options.fixedContainerClass;
70-
}
71-
});
72-
this._dispatchRefresh();
61+
this._refreshView();
7362
};
7463

7564
/*
@@ -103,6 +92,24 @@ FixedFootnotes.prototype.removeRefreshListener = function(listener) {
10392
* From here: "private" methods that user is not supposed to call directly.
10493
*/
10594

95+
/*
96+
* Refresh the view.
97+
*/
98+
FixedFootnotes.prototype._refreshView = function() {
99+
var self = this;
100+
util.emptyElement(this._fixedContainerList);
101+
this._fixedContainer.className = this.options.fixedContainerClass + " empty";
102+
this._getReferences().forEach(function(reference) {
103+
var note = self._getNoteFromRef(reference);
104+
if (!note) return;
105+
if (util.isElementInViewport(reference, self._window) && !util.isElementInViewport(note, self._window)) {
106+
self._displayNote(note);
107+
self._fixedContainer.className = self.options.fixedContainerClass;
108+
}
109+
});
110+
this._dispatchRefresh();
111+
};
112+
106113
/*
107114
* Create the fixed container that will host the footnotes.
108115
*/

0 commit comments

Comments
 (0)