diff --git a/app/assets/javascripts/discourse/tests/acceptance/click-track-test.js b/app/assets/javascripts/discourse/tests/acceptance/click-track-test.js index a335e1716b6..a006e4984ad 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/click-track-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/click-track-test.js @@ -1,30 +1,23 @@ import { click, currentURL, visit } from "@ember/test-helpers"; import { test } from "qunit"; -import { - acceptance, - count, - exists, -} from "discourse/tests/helpers/qunit-helpers"; - -acceptance("Click Track", function (needs) { - let tracked = false; - needs.pretender((server, helper) => { - server.post("/clicks/track", () => { - tracked = true; - return helper.response({ success: "OK" }); - }); - }); +import pretender, { response } from "discourse/tests/helpers/create-pretender"; +import { acceptance } from "discourse/tests/helpers/qunit-helpers"; +acceptance("Click Track", function () { test("Do not track mentions", async function (assert) { + pretender.post("/clicks/track", () => { + assert.true(false, "it should not track this click"); + return response({ success: "OK" }); + }); + await visit("/t/internationalization-localization/280"); - assert.ok(!exists(".user-card.show"), "card should not appear"); + assert.dom(".user-card").hasNoClass("show", "card should not appear"); await click('article[data-post-id="3651"] a.mention'); - assert.strictEqual(count(".user-card.show"), 1, "card appear"); + assert.dom(".user-card").hasClass("show", "card appears"); assert.strictEqual( currentURL(), "/t/internationalization-localization/280" ); - assert.ok(!tracked); }); }); diff --git a/app/assets/javascripts/discourse/tests/unit/lib/click-track-test.js b/app/assets/javascripts/discourse/tests/unit/lib/click-track-test.js index 4135b8aa9f3..30c694ffe1d 100644 --- a/app/assets/javascripts/discourse/tests/unit/lib/click-track-test.js +++ b/app/assets/javascripts/discourse/tests/unit/lib/click-track-test.js @@ -1,6 +1,5 @@ import { setupTest } from "ember-qunit"; -import $ from "jquery"; -import { module, skip, test } from "qunit"; +import { module, test } from "qunit"; import sinon from "sinon"; import ClickTrack from "discourse/lib/click-track"; import DiscourseURL from "discourse/lib/url"; @@ -12,7 +11,24 @@ import { setPrefix } from "discourse-common/lib/get-url"; const track = ClickTrack.trackClick; function generateClickEventOn(selector) { - return $.Event("click", { currentTarget: fixture(selector) }); + const event = new MouseEvent("click"); + sinon.stub(event, "currentTarget").get(() => fixture(selector)); + return event; +} + +function badgeClickCount(assert, id, expected) { + track(generateClickEventOn(`#${id}`)); + const badge = fixture(`#${id}`).querySelector("span.badge"); + assert.strictEqual(parseInt(badge.innerHTML, 10), expected); +} + +function testOpenInANewTab(description, clickEventModifier) { + test(description, async function (assert) { + const clickEvent = generateClickEventOn("a"); + clickEventModifier(clickEvent); + assert.true(track(clickEvent)); + assert.strictEqual(clickEvent.defaultPrevented, false); + }); } module("Unit | Utility | click-track", function (hooks) { @@ -21,7 +37,7 @@ module("Unit | Utility | click-track", function (hooks) { hooks.beforeEach(function () { logIn(); - let win = { focus: function () {} }; + const win = { focus: function () {} }; sinon.stub(window, "open").returns(win); sinon.stub(win, "focus"); @@ -60,32 +76,37 @@ module("Unit | Utility | click-track", function (hooks) { `; }); - skip("tracks internal URLs", async function (assert) { + test("tracks internal URLs", async function (assert) { + pretender.get("/session/csrf", () => { + assert.true(false, "should not request a csrf token"); + }); + sinon.stub(DiscourseURL, "origin").returns("http://discuss.domain.com"); const done = assert.async(); pretender.post("/clicks/track", (request) => { - assert.ok( + assert.strictEqual( request.requestBody, "url=http%3A%2F%2Fdiscuss.domain.com&post_id=42&topic_id=1337" ); done(); + return [200, {}, ""]; }); - assert.notOk(track(generateClickEventOn("#same-site"))); + assert.false(track(generateClickEventOn("#same-site"))); }); test("does not track elements with no href", async function (assert) { - assert.ok(track(generateClickEventOn(".a-without-href"))); + assert.true(track(generateClickEventOn(".a-without-href"))); }); test("does not track attachments", async function (assert) { sinon.stub(DiscourseURL, "origin").returns("http://discuss.domain.com"); - pretender.post("/clicks/track", () => assert.ok(false)); + pretender.post("/clicks/track", () => assert.true(false)); - assert.notOk(track(generateClickEventOn(".attachment"))); - assert.ok( + assert.false(track(generateClickEventOn(".attachment"))); + assert.true( DiscourseURL.redirectTo.calledWith( "http://discuss.domain.com/uploads/default/1234/1532357280.txt" ) @@ -94,20 +115,34 @@ module("Unit | Utility | click-track", function (hooks) { test("routes to internal urls", async function (assert) { setPrefix("/forum"); - pretender.post("/clicks/track", () => [200, {}, ""]); + + pretender.get("/forum/session/csrf", () => { + assert.true(false, "should not request a csrf token"); + }); + pretender.get("/session/csrf", () => { + assert.true(false, "should not request a csrf token"); + }); + + pretender.post("/clicks/track", () => { + assert.step("tracking"); + return [200, {}, ""]; + }); + await track(generateClickEventOn(".prefix-url"), null, { returnPromise: true, }); - assert.ok(DiscourseURL.routeTo.calledWith("/forum/thing")); + assert.true(DiscourseURL.routeTo.calledWith("/forum/thing")); + assert.verifySteps(["tracking"]); }); test("routes to absolute internal urls", async function (assert) { setPrefix("/forum"); pretender.post("/clicks/track", () => [200, {}, ""]); + await track(generateClickEventOn(".abs-prefix-url"), null, { returnPromise: true, }); - assert.ok( + assert.true( DiscourseURL.routeTo.calledWith(window.location.origin + "/forum/thing") ); }); @@ -120,82 +155,78 @@ module("Unit | Utility | click-track", function (hooks) { await track(generateClickEventOn(".diff-prefix-url"), null, { returnPromise: true, }); - assert.ok(DiscourseURL.redirectAbsolute.calledWith("/thing")); + assert.true(DiscourseURL.redirectAbsolute.calledWith("/thing")); }); - skip("tracks external URLs", async function (assert) { + test("tracks external URLs", async function (assert) { const done = assert.async(); pretender.post("/clicks/track", (request) => { - assert.ok( + assert.strictEqual( request.requestBody, "url=http%3A%2F%2Fwww.google.com&post_id=42&topic_id=1337" ); done(); + return [200, {}, ""]; }); - assert.notOk(track(generateClickEventOn("a"))); + assert.false(track(generateClickEventOn("a"))); }); - skip("tracks external URLs when opening in another window", async function (assert) { + test("tracks external URLs when opening in another window", async function (assert) { User.currentProp("user_option.external_links_in_new_tab", true); const done = assert.async(); pretender.post("/clicks/track", (request) => { - assert.ok( + assert.strictEqual( request.requestBody, "url=http%3A%2F%2Fwww.google.com&post_id=42&topic_id=1337" ); done(); + return [200, {}, ""]; }); - assert.notOk(track(generateClickEventOn("a"))); - assert.ok(window.open.calledWith("http://www.google.com", "_blank")); + assert.false(track(generateClickEventOn("a"))); + assert.true(window.open.calledWith("http://www.google.com/", "_blank")); }); test("does not track clicks on lightboxes", async function (assert) { - assert.notOk(track(generateClickEventOn(".lightbox"))); + assert.false(track(generateClickEventOn(".lightbox"))); }); test("does not track clicks when forcibly disabled", async function (assert) { - assert.notOk(track(generateClickEventOn(".no-track-link"))); + assert.false(track(generateClickEventOn(".no-track-link"))); }); test("does not track clicks on back buttons", async function (assert) { - assert.notOk(track(generateClickEventOn(".back"))); + assert.false(track(generateClickEventOn(".back"))); }); test("does not track right clicks inside quotes", async function (assert) { const event = generateClickEventOn(".quote a:first-child"); - event.which = 3; - assert.ok(track(event)); + sinon.stub(event, "which").get(() => 3); + assert.true(track(event)); }); test("does not track clicks links in quotes", async function (assert) { User.currentProp("user_option.external_links_in_new_tab", true); - assert.notOk(track(generateClickEventOn(".quote a:last-child"))); - assert.ok(window.open.calledWith("https://google.com/", "_blank")); + assert.false(track(generateClickEventOn(".quote a:last-child"))); + assert.true(window.open.calledWith("https://google.com/", "_blank")); }); test("does not track clicks on hashtags for categories and tags", async function (assert) { - assert.notOk(track(generateClickEventOn(".hashtag"))); - assert.notOk(track(generateClickEventOn(".hashtag-cooked"))); + assert.false(track(generateClickEventOn(".hashtag"))); + assert.false(track(generateClickEventOn(".hashtag-cooked"))); }); test("returns true for tracking mentions and group mentions so the card can appear", async function (assert) { - assert.ok(track(generateClickEventOn(".mention"))); - assert.ok(track(generateClickEventOn(".mention-group"))); + assert.true(track(generateClickEventOn(".mention"))); + assert.true(track(generateClickEventOn(".mention-group"))); }); test("does not track clicks on mailto", async function (assert) { - assert.ok(track(generateClickEventOn(".mailto"))); + assert.true(track(generateClickEventOn(".mailto"))); }); - function badgeClickCount(assert, id, expected) { - track(generateClickEventOn(`#${id}`)); - const badge = fixture(`#${id}`).querySelector("span.badge"); - assert.strictEqual(parseInt(badge.innerHTML, 10), expected); - } - test("does not update badge clicks on my own link", async function (assert) { sinon.stub(User, "currentProp").withArgs("id").returns(314); badgeClickCount(assert, "with-badge", 1); @@ -212,37 +243,28 @@ module("Unit | Utility | click-track", function (hooks) { badgeClickCount(assert, "with-badge", 2); }); - function testOpenInANewTab(description, clickEventModifier) { - test(description, async function (assert) { - let 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; + sinon.stub(clickEvent, "shiftKey").get(() => true); } ); testOpenInANewTab( "it opens in a new tab when pressing meta", (clickEvent) => { - clickEvent.metaKey = true; + sinon.stub(clickEvent, "metaKey").get(() => true); } ); testOpenInANewTab( "it opens in a new tab when pressing ctrl", (clickEvent) => { - clickEvent.ctrlKey = true; + sinon.stub(clickEvent, "ctrlKey").get(() => true); } ); testOpenInANewTab("it opens in a new tab on middle click", (clickEvent) => { - clickEvent.button = 2; + sinon.stub(clickEvent, "button").get(() => 2); }); });