import DiscourseURL from "discourse/lib/url"; import ClickTrack from "discourse/lib/click-track"; import { logIn } from "helpers/qunit-helpers"; QUnit.module("lib:click-track", { beforeEach() { logIn(); let win = { focus: function() {} }; sandbox.stub(window, "open").returns(win); sandbox.stub(win, "focus"); sandbox.stub(DiscourseURL, "routeTo"); sandbox.stub(DiscourseURL, "redirectTo"); sessionStorage.clear(); fixture().html( `
` ); } }); var track = ClickTrack.trackClick; function generateClickEventOn(selector) { return $.Event("click", { currentTarget: fixture(selector).first() }); } QUnit.test("tracks internal URLs", async assert => { assert.expect(2); sandbox.stub(DiscourseURL, "origin").returns("http://discuss.domain.com"); const done = assert.async(); /* global server */ server.get("/clicks/track", request => { assert.ok( request.url.indexOf( "url=http%3A%2F%2Fdiscuss.domain.com&post_id=42&topic_id=1337" ) !== -1 ); done(); }); assert.notOk(track(generateClickEventOn("#same-site"))); }); QUnit.test("does not track attachments", async assert => { assert.expect(1); sandbox.stub(DiscourseURL, "origin").returns("http://discuss.domain.com"); /* global server */ server.get("/clicks/track", () => assert.ok(false)); assert.ok(track(generateClickEventOn(".attachment"))); }); QUnit.test("tracks external URLs", async assert => { assert.expect(2); const done = assert.async(); /* global server */ server.get("/clicks/track", request => { assert.ok( request.url.indexOf( "url=http%3A%2F%2Fwww.google.com&post_id=42&topic_id=1337" ) !== -1 ); done(); }); assert.notOk(track(generateClickEventOn("a"))); }); QUnit.test( "tracks external URLs when opening in another window", async assert => { assert.expect(3); Discourse.User.currentProp("external_links_in_new_tab", true); const done = assert.async(); /* global server */ server.get("/clicks/track", request => { assert.ok( request.url.indexOf( "url=http%3A%2F%2Fwww.google.com&post_id=42&topic_id=1337" ) !== -1 ); done(); }); assert.notOk(track(generateClickEventOn("a"))); assert.ok(window.open.calledWith("http://www.google.com", "_blank")); } ); QUnit.test("does not track clicks on lightboxes", async assert => { assert.notOk(track(generateClickEventOn(".lightbox"))); }); QUnit.test("does not track clicks when forcibly disabled", async assert => { assert.notOk(track(generateClickEventOn(".no-track-link"))); }); QUnit.test("does not track clicks on back buttons", async assert => { assert.notOk(track(generateClickEventOn(".back"))); }); QUnit.test("does not track right clicks inside quotes", async assert => { const event = generateClickEventOn(".quote a:first-child"); event.which = 3; assert.ok(track(event)); }); QUnit.test("does not track clicks links in quotes", async assert => { Discourse.User.currentProp("external_links_in_new_tab", true); assert.notOk(track(generateClickEventOn(".quote a:last-child"))); assert.ok(window.open.calledWith("https://google.com", "_blank")); }); QUnit.test("does not track clicks on category badges", async assert => { assert.notOk(track(generateClickEventOn(".hashtag"))); }); QUnit.test("does not track clicks on mailto", async assert => { assert.ok(track(generateClickEventOn(".mailto"))); }); QUnit.test("removes the href and put it as a data attribute", async assert => { Discourse.User.currentProp("external_links_in_new_tab", true); assert.notOk(track(generateClickEventOn("a"))); var $link = fixture("a").first(); assert.ok($link.hasClass("no-href")); assert.equal($link.data("href"), "http://www.google.com"); assert.blank($link.attr("href")); assert.ok($link.data("auto-route")); assert.ok(window.open.calledWith("http://www.google.com", "_blank")); }); asyncTestDiscourse("restores the href after a while", async assert => { assert.expect(2); assert.notOk(track(generateClickEventOn("a"))); const done = assert.async(); setTimeout(function() { done(); assert.equal(fixture("a").attr("href"), "http://www.google.com"); }, 75); }); function badgeClickCount(assert, id, expected) { track(generateClickEventOn("#" + id)); var $badge = $("span.badge", fixture("#" + id).first()); assert.equal(parseInt($badge.html(), 10), expected); } QUnit.test("does not update badge clicks on my own link", async assert => { sandbox .stub(Discourse.User, "currentProp") .withArgs("id") .returns(314); badgeClickCount(assert, "with-badge", 1); }); QUnit.test("does not update badge clicks in my own post", async assert => { sandbox .stub(Discourse.User, "currentProp") .withArgs("id") .returns(3141); badgeClickCount(assert, "with-badge-but-not-mine", 1); }); QUnit.test("updates badge counts correctly", async assert => { badgeClickCount(assert, "inside-onebox", 1); badgeClickCount(assert, "inside-onebox-forced", 2); badgeClickCount(assert, "with-badge", 2); }); function testOpenInANewTab(description, clickEventModifier) { test(description, async assert => { var clickEvent = generateClickEventOn("a"); clickEventModifier(clickEvent); assert.ok(track(clickEvent)); assert.notOk(clickEvent.defaultPrevented); }); } testOpenInANewTab("it opens in a new tab when pressing shift", clickEvent => { clickEvent.shiftKey = true; }); testOpenInANewTab("it opens in a new tab when pressing meta", clickEvent => { clickEvent.metaKey = true; }); testOpenInANewTab("it opens in a new tab when pressing ctrl", clickEvent => { clickEvent.ctrlKey = true; }); testOpenInANewTab("it opens in a new tab on middle click", clickEvent => { clickEvent.button = 2; });