Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 15 additions & 13 deletions src/readthedocs-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,17 +69,19 @@ export function getReadTheDocsUserConfig(sendUrlParam) {
// this data is ready to be consumed under `event.detail.data()`.
const userApiUrl = _getApiUrl(sendUrlParam, metadataAddonsAPIVersion);

fetch(userApiUrl, {
method: "GET",
}).then((response) => {
if (!response.ok) {
return reject(
"Error hitting addons API endpoint for user api-version",
);
}
// Return the data in the API version requested.
return resolve(response.json());
});
return resolve(
fetch(userApiUrl, {
method: "GET",
}).then((response) => {
if (!response.ok) {
return reject(
"Error hitting addons API endpoint for user api-version",
);
}
// Return the data in the API version requested.
return response.json();
}),
);
}

// If the API versions match, we return `undefined`.
Expand Down Expand Up @@ -124,8 +126,8 @@ export function getReadTheDocsConfig(sendUrlParam) {
// event was fired can still get access to the data
globalThis.ReadTheDocsEventData = new ReadTheDocsEventData(dataEvent);

// Trigger the addons data ready CustomEvent to with the data the user is expecting.
return dispatchEvent(
// Trigger the addons data ready CustomEvent with the data the user is expecting.
dispatchEvent(
EVENT_READTHEDOCS_ADDONS_USER_DATA_READY,
document,
new ReadTheDocsEventData(dataEvent),
Expand Down
3 changes: 1 addition & 2 deletions tests/__snapshots__/search.test.snap.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

88 changes: 88 additions & 0 deletions tests/hotkeys.test.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<html>
<head>
<meta name="readthedocs-http-status" content="200" />
</head>
<body>
<script type="module">
import { default as sinon } from "sinon";
import { expect, elementUpdated } from "@open-wc/testing";
import { runTests } from "@web/test-runner-mocha";
import * as events from "../src/events";
import * as hotkeys from "../src/hotkeys";

let config;

runTests(async () => {
beforeEach(() => {
config = {
addons: {
hotkeys: {
enabled: true,
doc_diff: {
enabled: true,
trigger: "KeyD",
},
search: {
enabled: true,
trigger: "Slash",
},
},
},
};
});

afterEach(() => {
sinon.restore();
});

describe("HotKeys tests", () => {
it("trigger docdiff when pressing 'd'", async () => {
const addon = new hotkeys.HotKeysAddon(config);
const element = document.querySelector("readthedocs-hotkeys");
await elementUpdated(element);

// Empty shadowDom
await expect(element).shadowDom.to.equal("");

const fakeFunction = sinon.fake();
document.addEventListener(
events.EVENT_READTHEDOCS_DOCDIFF_ADDED_REMOVED_SHOW,
(event) => {
fakeFunction();
},
);

const event = new Event("keydown");
event.code = "KeyD";
document.dispatchEvent(event);

expect(fakeFunction.calledOnce).to.be.true;
});

it("trigger search modal when pressing '/'", async () => {
const addon = new hotkeys.HotKeysAddon(config);
const element = document.querySelector("readthedocs-hotkeys");
await elementUpdated(element);

// Empty shadowDom
await expect(element).shadowDom.to.equal("");

const fakeFunction = sinon.fake();
document.addEventListener(
events.EVENT_READTHEDOCS_SEARCH_SHOW,
(event) => {
fakeFunction();
},
);

const event = new Event("keydown");
event.code = "Slash";
document.dispatchEvent(event);

expect(fakeFunction.calledOnce).to.be.true;
});
});
});
</script>
</body>
</html>
62 changes: 48 additions & 14 deletions tests/readthedocs-config.test.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import { expect, elementUpdated } from "@open-wc/testing";
import { runTests } from "@web/test-runner-mocha";
import * as readthedocsConfig from "../src/readthedocs-config";
import * as events from "../src/events";
import * as utils from "../src/utils";

let server;
Expand All @@ -20,6 +21,8 @@
beforeEach(() => {
// Create a sinon fake server to mock requests
server = sinon.fakeServer.create();
server.respondImmediately = true;

if (metadataAddonsAPIVersion) {
metadataAddonsAPIVersion.remove();
}
Expand Down Expand Up @@ -54,17 +57,10 @@

it("fetch config from API endpoint", async () => {
const matchMockedUrl = new RegExp(`^/_/addons/`, "g");
server.respondWith("GET", matchMockedUrl, [
200,
{},
"fake response body",
]);
server.respondWith("GET", matchMockedUrl, [200, {}, "{}"]);

const config = readthedocsConfig.getReadTheDocsConfig(false);

// Respond to all the request waiting for a response
server.respond();

expect(server.requests).to.have.length(1);
expect(server.requests[0].status).to.be.equal(200);
expect(server.requests[0].method).to.be.equal("GET");
Expand All @@ -78,18 +74,22 @@
metadataAddonsAPIVersion.content = "2";
document.head.appendChild(metadataAddonsAPIVersion);

// Response 204 on requests made to Read the Docs analytics' API
// Response 200 on requests made to Read the Docs analytics' API
const matchMockedUrl = new RegExp(`^/_/addons/`, "g");
server.respondWith("GET", matchMockedUrl, [
200,
{},
"fake response body",
'{"addons": {}, "builds": {"current": {"id": 12345}}, "projects": {}, "versions": {}}',
]);

const config = readthedocsConfig.getReadTheDocsUserConfig(true);

// Respond to all the request waiting for a response
server.respond();
const config =
await readthedocsConfig.getReadTheDocsUserConfig(true);
expect(config).to.deep.equal({
addons: {},
builds: { current: { id: 12345 } },
projects: {},
versions: {},
});

expect(server.requests).to.have.length(1);
expect(server.requests[0].status).to.be.equal(200);
Expand All @@ -98,6 +98,40 @@
/^\/_\/addons\/\?client-version=.+&api-version=2&url=.+$/;
expect(server.requests[0].url).to.match(matchApiUrl);
});

it("check readthedocs-addons-data-ready event", async () => {
// Response 200 on requests made to Read the Docs analytics' API
const matchMockedUrl = new RegExp(`^/_/addons/`, "g");
server.respondWith("GET", matchMockedUrl, [
200,
{},
'{"test": "readthedocs-addons-data-ready", "builds": {"current": {"id": 12345}}}',
]);

let eventData;
const fakeFunction = sinon.fake();
document.addEventListener(
events.EVENT_READTHEDOCS_ADDONS_USER_DATA_READY,
(event) => {
// Store the event data to check later
eventData = event.detail.data(true);

// Call the `fakeFunction` inside the event listener to check later it was called once.
fakeFunction();
},
);

const config = await readthedocsConfig.getReadTheDocsConfig(true);
expect(fakeFunction.calledOnce).to.be.true;
expect(eventData).to.deep.equal({
test: "readthedocs-addons-data-ready",
builds: {
current: {
id: 12345,
},
},
});
});
});
});
</script>
Expand Down
4 changes: 3 additions & 1 deletion tests/search.test.html
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,9 @@
document.dispatchEvent(searchEvent);

await elementUpdated(element);
await expect(element).shadowDom.to.equalSnapshot();
await expect(element).shadowDom.to.equalSnapshot({
ignoreAttributes: [{ tags: ["form"], attributes: ["class"] }],
});
});

it("initial trigger by event and DOM check with filters", async () => {
Expand Down
51 changes: 43 additions & 8 deletions tests/utils.test.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
</head>
<body>
<script type="module">
import { default as sinon } from "sinon";
import { expect, elementUpdated } from "@open-wc/testing";
import { runTests } from "@web/test-runner-mocha";
import * as docdiff from "../src/docdiff";
import * as utils from "../src/utils";
import * as events from "../src/events";
import * as readthedocsConfig from "../src/readthedocs-config";
Expand All @@ -31,6 +33,8 @@
);
eventListener = null;
}

sinon.restore();
});

describe("DocumentationTool tests", () => {
Expand All @@ -42,10 +46,7 @@
document.head.appendChild(element);

eventListener = function func(event) {
// We need to use `JSON.stringify` because objects are not equal in javascript
expect(JSON.stringify(event.detail.data())).to.be.equal(
JSON.stringify({ addons: "data" }),
);
expect(event.detail.data()).to.deep.equal({ addons: "data" });
expect(event.detail.httpStatus()).to.be.equal("200");
};

Expand Down Expand Up @@ -87,10 +88,7 @@

it("use readthedocs-addons-data-ready without META tag and internal=true", async () => {
eventListener = function func(event) {
// We need to use `JSON.stringify` because objects are not equal in javascript
expect(JSON.stringify(event.detail.data(true))).to.be.equal(
JSON.stringify({ addons: "data" }),
);
expect(event.detail.data(true)).to.deep.equal({ addons: "data" });
};
document.addEventListener(
events.EVENT_READTHEDOCS_ADDONS_USER_DATA_READY,
Expand All @@ -104,6 +102,43 @@
);
});

it("trigger URL_CHANGED on SPA without GET parameters", async () => {
utils.setupHistoryEvents();

const fakeFunction = sinon.fake();
window.addEventListener(
events.EVENT_READTHEDOCS_URL_CHANGED,
(event) => {
fakeFunction();
},
);

expect(fakeFunction.notCalled).to.be.true;
history.pushState({}, "", "#newpage");
expect(fakeFunction.calledOnce).to.be.true;
});

it("trigger URL_CHANGED on SPA with `?readthedocs-diff-chunk` parameter", async () => {
utils.setupHistoryEvents();

const fakeFunction = sinon.fake();
window.addEventListener(
events.EVENT_READTHEDOCS_URL_CHANGED,
(event) => {
fakeFunction();
},
);

expect(fakeFunction.notCalled).to.be.true;

const url = new URL(window.location.href);
url.searchParams.set(docdiff.DOCDIFF_CHUNK_URL_PARAM, 1);
history.pushState({}, "", url);

expect(fakeFunction.notCalled).to.be.true;
expect(fakeFunction.calledOnce).to.be.false;
});

it("Sphinx Alabaster", async () => {
element = document.createElement("link");
element.href = "_static/alabaster.css";
Expand Down