diff --git a/frontend_tests/node_tests/components.js b/frontend_tests/node_tests/components.js
index 32762ebbc2..6514d20cdf 100644
--- a/frontend_tests/node_tests/components.js
+++ b/frontend_tests/node_tests/components.js
@@ -7,6 +7,159 @@ const _ = require("lodash");
const {set_global, zrequire} = require("../zjsunit/namespace");
const {run_test} = require("../zjsunit/test");
+let keydown_f;
+let click_f;
+const tabs = [];
+let focused_tab;
+
+function make_tab(i) {
+ const self = {};
+
+ assert.equal(tabs.length, i);
+
+ self.stub = true;
+ self.class = [];
+
+ self.addClass = (c) => {
+ self.class += " " + c;
+ const tokens = self.class.trim().split(/ +/);
+ self.class = _.uniq(tokens).join(" ");
+ };
+
+ self.removeClass = (c) => {
+ const tokens = self.class.trim().split(/ +/);
+ self.class = _.without(tokens, c).join(" ");
+ };
+
+ self.hasClass = (c) => {
+ const tokens = self.class.trim().split(/ +/);
+ return tokens.includes(c);
+ };
+
+ self.data = (name) => {
+ assert.equal(name, "tab-id");
+ return i;
+ };
+
+ self.text = (text) => {
+ assert.equal(
+ text,
+ [
+ "translated: Keyboard shortcuts",
+ "translated: Message formatting",
+ "translated: Search operators",
+ ][i],
+ );
+ };
+
+ self.trigger = (type) => {
+ if (type === "focus") {
+ focused_tab = i;
+ }
+ };
+
+ tabs.push(self);
+
+ return self;
+}
+
+const ind_tab = (function () {
+ const self = {};
+
+ self.stub = true;
+
+ self.on = (name, f) => {
+ if (name === "click") {
+ click_f = f;
+ } else if (name === "keydown") {
+ keydown_f = f;
+ }
+ };
+
+ self.removeClass = (c) => {
+ for (const tab of tabs) {
+ tab.removeClass(c);
+ }
+ };
+
+ self.eq = (idx) => tabs[idx];
+
+ return self;
+})();
+
+const switcher = (function () {
+ const self = {};
+
+ self.stub = true;
+
+ self.children = [];
+
+ self.classList = new Set();
+
+ self.append = (child) => {
+ self.children.push(child);
+ };
+
+ self.addClass = (c) => {
+ self.classList.add(c);
+ self.addedClass = c;
+ };
+
+ self.find = (sel) => {
+ switch (sel) {
+ case ".ind-tab":
+ return ind_tab;
+ default:
+ throw new Error("unknown selector: " + sel);
+ }
+ };
+
+ return self;
+})();
+
+set_global("$", (sel, attributes) => {
+ if (sel.stub) {
+ // The component often redundantly re-wraps objects.
+ return sel;
+ }
+
+ switch (sel) {
+ case "
": {
+ const tab_id = attributes["data-tab-id"];
+ assert.deepEqual(
+ attributes,
+ [
+ {
+ class: "ind-tab",
+ "data-tab-key": "keyboard-shortcuts",
+ "data-tab-id": 0,
+ tabindex: 0,
+ },
+ {
+ class: "ind-tab",
+ "data-tab-key": "message-formatting",
+ "data-tab-id": 1,
+ tabindex: 0,
+ },
+ {
+ class: "ind-tab",
+ "data-tab-key": "search-operators",
+ "data-tab-id": 2,
+ tabindex: 0,
+ },
+ ][tab_id],
+ );
+ return make_tab(tab_id);
+ }
+ default:
+ throw new Error("unknown selector: " + sel);
+ }
+});
+
const components = zrequire("components");
const noop = () => {};
@@ -15,160 +168,7 @@ const LEFT_KEY = {which: 37, preventDefault: noop, stopPropagation: noop};
const RIGHT_KEY = {which: 39, preventDefault: noop, stopPropagation: noop};
run_test("basics", () => {
- let keydown_f;
- let click_f;
- const tabs = [];
- let focused_tab;
let callback_args;
-
- function make_tab(i) {
- const self = {};
-
- assert.equal(tabs.length, i);
-
- self.stub = true;
- self.class = [];
-
- self.addClass = (c) => {
- self.class += " " + c;
- const tokens = self.class.trim().split(/ +/);
- self.class = _.uniq(tokens).join(" ");
- };
-
- self.removeClass = (c) => {
- const tokens = self.class.trim().split(/ +/);
- self.class = _.without(tokens, c).join(" ");
- };
-
- self.hasClass = (c) => {
- const tokens = self.class.trim().split(/ +/);
- return tokens.includes(c);
- };
-
- self.data = (name) => {
- assert.equal(name, "tab-id");
- return i;
- };
-
- self.text = (text) => {
- assert.equal(
- text,
- [
- "translated: Keyboard shortcuts",
- "translated: Message formatting",
- "translated: Search operators",
- ][i],
- );
- };
-
- self.trigger = (type) => {
- if (type === "focus") {
- focused_tab = i;
- }
- };
-
- tabs.push(self);
-
- return self;
- }
-
- const ind_tab = (function () {
- const self = {};
-
- self.stub = true;
-
- self.on = (name, f) => {
- if (name === "click") {
- click_f = f;
- } else if (name === "keydown") {
- keydown_f = f;
- }
- };
-
- self.removeClass = (c) => {
- for (const tab of tabs) {
- tab.removeClass(c);
- }
- };
-
- self.eq = (idx) => tabs[idx];
-
- return self;
- })();
-
- const switcher = (function () {
- const self = {};
-
- self.stub = true;
-
- self.children = [];
-
- self.classList = new Set();
-
- self.append = (child) => {
- self.children.push(child);
- };
-
- self.addClass = (c) => {
- self.classList.add(c);
- self.addedClass = c;
- };
-
- self.find = (sel) => {
- switch (sel) {
- case ".ind-tab":
- return ind_tab;
- default:
- throw new Error("unknown selector: " + sel);
- }
- };
-
- return self;
- })();
-
- set_global("$", (sel, attributes) => {
- if (sel.stub) {
- // The component often redundantly re-wraps objects.
- return sel;
- }
-
- switch (sel) {
- case "
":
- return switcher;
- case "
":
- return switcher;
- case "
": {
- const tab_id = attributes["data-tab-id"];
- assert.deepEqual(
- attributes,
- [
- {
- class: "ind-tab",
- "data-tab-key": "keyboard-shortcuts",
- "data-tab-id": 0,
- tabindex: 0,
- },
- {
- class: "ind-tab",
- "data-tab-key": "message-formatting",
- "data-tab-id": 1,
- tabindex: 0,
- },
- {
- class: "ind-tab",
- "data-tab-key": "search-operators",
- "data-tab-id": 2,
- tabindex: 0,
- },
- ][tab_id],
- );
- return make_tab(tab_id);
- }
- default:
- throw new Error("unknown selector: " + sel);
- }
- });
-
let callback_value;
let widget = null;