2020-08-01 03:43:15 +02:00
|
|
|
"use strict";
|
|
|
|
|
2020-11-30 23:46:45 +01:00
|
|
|
const {strict: assert} = require("assert");
|
|
|
|
|
2020-12-01 00:02:16 +01:00
|
|
|
const {set_global, with_overrides, zrequire} = require("../zjsunit/namespace");
|
2021-02-13 03:46:14 +01:00
|
|
|
const {make_stub} = require("../zjsunit/stub");
|
2020-12-01 00:39:47 +01:00
|
|
|
const {run_test} = require("../zjsunit/test");
|
2020-12-01 00:02:16 +01:00
|
|
|
|
2017-03-20 06:05:54 +01:00
|
|
|
// Important note on these tests:
|
|
|
|
//
|
|
|
|
// The way the Zulip hotkey tests work is as follows. First, we set
|
|
|
|
// up various contexts by monkey-patching the various hotkeys exports
|
2017-05-27 15:40:54 +02:00
|
|
|
// functions (like overlays.settings_open). Within that context, to
|
2017-03-20 06:05:54 +01:00
|
|
|
// test whether a given key (e.g. `x`) results in a specific function
|
|
|
|
// (e.g. `ui.foo()`), we fail to import any modules other than
|
|
|
|
// hotkey.js so that accessing them will result in a ReferenceError.
|
|
|
|
//
|
|
|
|
// Then we create a stub `ui.foo`, and call the hotkey function. If
|
|
|
|
// it calls any external module other than `ui.foo`, it'll crash.
|
|
|
|
// Future work includes making sure it actually does call `ui.foo()`.
|
|
|
|
|
2020-07-25 23:59:49 +02:00
|
|
|
const emoji_codes = zrequire("emoji_codes", "generated/emoji/emoji_codes.json");
|
|
|
|
|
2020-07-15 01:29:15 +02:00
|
|
|
set_global("navigator", {
|
|
|
|
platform: "",
|
2018-03-29 22:29:10 +02:00
|
|
|
});
|
|
|
|
|
2020-07-15 00:34:28 +02:00
|
|
|
set_global("page_params", {});
|
2017-09-16 17:30:07 +02:00
|
|
|
|
2021-02-10 04:53:22 +01:00
|
|
|
let overlays = set_global("overlays", {});
|
2017-05-10 00:37:08 +02:00
|
|
|
|
2018-04-12 22:38:31 +02:00
|
|
|
// jQuery stuff should go away if we make an initialize() method.
|
2020-07-15 01:29:15 +02:00
|
|
|
set_global("document", "document-stub");
|
2017-03-14 18:29:38 +01:00
|
|
|
|
2020-07-25 00:12:17 +02:00
|
|
|
const emoji = zrequire("emoji", "shared/js/emoji");
|
2020-07-25 23:59:49 +02:00
|
|
|
|
|
|
|
emoji.initialize({
|
|
|
|
realm_emoji: {},
|
|
|
|
emoji_codes,
|
|
|
|
});
|
|
|
|
|
2021-02-11 01:23:23 +01:00
|
|
|
const activity = zrequire("activity");
|
2020-07-15 01:29:15 +02:00
|
|
|
const hotkey = zrequire("hotkey");
|
|
|
|
zrequire("common");
|
2017-03-10 22:24:54 +01:00
|
|
|
|
2021-02-11 01:23:23 +01:00
|
|
|
const compose_actions = set_global("compose_actions", {});
|
|
|
|
const condense = set_global("condense", {});
|
|
|
|
const drafts = set_global("drafts", {});
|
|
|
|
const hashchange = set_global("hashchange", {});
|
2020-07-26 14:06:28 +02:00
|
|
|
set_global("info_overlay", {});
|
2021-02-11 01:23:23 +01:00
|
|
|
const lightbox = set_global("lightbox", {});
|
2021-02-10 04:53:22 +01:00
|
|
|
const list_util = set_global("list_util", {});
|
2021-02-11 01:23:23 +01:00
|
|
|
const message_edit = set_global("message_edit", {});
|
|
|
|
const muting_ui = set_global("muting_ui", {});
|
|
|
|
const narrow = set_global("narrow", {});
|
|
|
|
const navigate = set_global("navigate", {});
|
|
|
|
const reactions = set_global("reactions", {});
|
|
|
|
const search = set_global("search", {});
|
|
|
|
const stream_list = set_global("stream_list", {});
|
|
|
|
const subs = set_global("subs", {});
|
2017-04-04 18:14:27 +02:00
|
|
|
|
2020-07-15 01:29:15 +02:00
|
|
|
set_global("current_msg_list", {
|
2020-07-20 22:18:43 +02:00
|
|
|
selected_id() {
|
2017-03-19 05:19:36 +01:00
|
|
|
return 42;
|
|
|
|
},
|
2020-07-20 22:18:43 +02:00
|
|
|
selected_message() {
|
2017-03-19 05:19:36 +01:00
|
|
|
return {
|
|
|
|
sent_by_me: true,
|
|
|
|
flags: ["read", "starred"],
|
|
|
|
};
|
|
|
|
},
|
2020-07-20 22:18:43 +02:00
|
|
|
selected_row() {},
|
|
|
|
get_row() {
|
2019-04-06 15:57:48 +02:00
|
|
|
return 101;
|
|
|
|
},
|
2017-03-10 22:24:54 +01:00
|
|
|
});
|
|
|
|
|
2020-07-15 00:34:28 +02:00
|
|
|
function return_true() {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
function return_false() {
|
|
|
|
return false;
|
|
|
|
}
|
2017-03-10 22:24:54 +01:00
|
|
|
|
2021-02-11 01:23:23 +01:00
|
|
|
function stubbing(module, func_name_to_stub, test_function) {
|
2020-12-01 00:02:16 +01:00
|
|
|
with_overrides((override) => {
|
2021-02-13 03:46:14 +01:00
|
|
|
const stub = make_stub();
|
|
|
|
override(module, func_name_to_stub, stub.f);
|
|
|
|
test_function(stub);
|
2017-03-10 22:24:54 +01:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2020-07-15 01:29:15 +02:00
|
|
|
run_test("mappings", () => {
|
2017-03-13 21:41:28 +01:00
|
|
|
function map_press(which, shiftKey) {
|
|
|
|
return hotkey.get_keypress_hotkey({
|
2020-07-20 22:18:43 +02:00
|
|
|
which,
|
|
|
|
shiftKey,
|
2017-03-13 21:41:28 +01:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-08-14 00:05:36 +02:00
|
|
|
function map_down(which, shiftKey, ctrlKey, metaKey) {
|
2017-03-13 21:41:28 +01:00
|
|
|
return hotkey.get_keydown_hotkey({
|
2020-07-20 22:18:43 +02:00
|
|
|
which,
|
|
|
|
shiftKey,
|
|
|
|
ctrlKey,
|
|
|
|
metaKey,
|
2017-03-13 21:41:28 +01:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// The next assertion protects against an iOS bug where we
|
|
|
|
// treat "!" as a hotkey, because iOS sends the wrong code.
|
|
|
|
assert.equal(map_press(33), undefined);
|
|
|
|
|
|
|
|
// Test page-up does work.
|
2020-07-15 01:29:15 +02:00
|
|
|
assert.equal(map_down(33).name, "page_up");
|
2017-03-13 21:41:28 +01:00
|
|
|
|
|
|
|
// Test other mappings.
|
2020-07-15 01:29:15 +02:00
|
|
|
assert.equal(map_down(9).name, "tab");
|
|
|
|
assert.equal(map_down(9, true).name, "shift_tab");
|
|
|
|
assert.equal(map_down(27).name, "escape");
|
|
|
|
assert.equal(map_down(37).name, "left_arrow");
|
|
|
|
assert.equal(map_down(13).name, "enter");
|
|
|
|
assert.equal(map_down(46).name, "delete");
|
|
|
|
assert.equal(map_down(13, true).name, "enter");
|
|
|
|
|
|
|
|
assert.equal(map_press(47).name, "search"); // slash
|
|
|
|
assert.equal(map_press(106).name, "vim_down"); // j
|
|
|
|
|
2020-08-11 02:09:14 +02:00
|
|
|
assert.equal(map_down(219, false, true).name, "escape"); // Ctrl + [
|
|
|
|
assert.equal(map_down(67, false, true).name, "copy_with_c"); // Ctrl + C
|
|
|
|
assert.equal(map_down(75, false, true).name, "search_with_k"); // Ctrl + K
|
|
|
|
assert.equal(map_down(83, false, true).name, "star_message"); // Ctrl + S
|
|
|
|
assert.equal(map_down(190, false, true).name, "narrow_to_compose_target"); // Ctrl + .
|
2017-03-19 19:26:13 +01:00
|
|
|
|
2017-03-13 21:41:28 +01:00
|
|
|
// More negative tests.
|
|
|
|
assert.equal(map_down(47), undefined);
|
|
|
|
assert.equal(map_press(27), undefined);
|
|
|
|
assert.equal(map_down(27, true), undefined);
|
2020-08-11 02:09:14 +02:00
|
|
|
assert.equal(map_down(86, false, true), undefined); // Ctrl + V
|
|
|
|
assert.equal(map_down(90, false, true), undefined); // Ctrl + Z
|
|
|
|
assert.equal(map_down(84, false, true), undefined); // Ctrl + T
|
|
|
|
assert.equal(map_down(82, false, true), undefined); // Ctrl + R
|
|
|
|
assert.equal(map_down(79, false, true), undefined); // Ctrl + O
|
|
|
|
assert.equal(map_down(80, false, true), undefined); // Ctrl + P
|
|
|
|
assert.equal(map_down(65, false, true), undefined); // Ctrl + A
|
|
|
|
assert.equal(map_down(70, false, true), undefined); // Ctrl + F
|
|
|
|
assert.equal(map_down(72, false, true), undefined); // Ctrl + H
|
|
|
|
assert.equal(map_down(88, false, true), undefined); // Ctrl + X
|
|
|
|
assert.equal(map_down(78, false, true), undefined); // Ctrl + N
|
|
|
|
assert.equal(map_down(77, false, true), undefined); // Ctrl + M
|
|
|
|
assert.equal(map_down(67, false, false, true), undefined); // Cmd + C
|
|
|
|
assert.equal(map_down(75, false, false, true), undefined); // Cmd + K
|
|
|
|
assert.equal(map_down(83, false, false, true), undefined); // Cmd + S
|
|
|
|
assert.equal(map_down(75, true, true), undefined); // Shift + Ctrl + K
|
|
|
|
assert.equal(map_down(83, true, true), undefined); // Shift + Ctrl + S
|
|
|
|
assert.equal(map_down(219, true, true, false), undefined); // Shift + Ctrl + [
|
|
|
|
|
|
|
|
// Cmd tests for MacOS
|
2020-12-01 00:57:57 +01:00
|
|
|
navigator.platform = "MacIntel";
|
2020-08-11 02:09:14 +02:00
|
|
|
assert.equal(map_down(219, false, true, false).name, "escape"); // Ctrl + [
|
|
|
|
assert.equal(map_down(219, false, false, true), undefined); // Cmd + [
|
|
|
|
assert.equal(map_down(67, false, true, true).name, "copy_with_c"); // Ctrl + C
|
|
|
|
assert.equal(map_down(67, false, true, false), undefined); // Cmd + C
|
|
|
|
assert.equal(map_down(75, false, false, true).name, "search_with_k"); // Cmd + K
|
|
|
|
assert.equal(map_down(75, false, true, false), undefined); // Ctrl + K
|
|
|
|
assert.equal(map_down(83, false, false, true).name, "star_message"); // Cmd + S
|
|
|
|
assert.equal(map_down(83, false, true, false), undefined); // Ctrl + S
|
|
|
|
assert.equal(map_down(190, false, false, true).name, "narrow_to_compose_target"); // Cmd + .
|
|
|
|
assert.equal(map_down(190, false, true, false), undefined); // Ctrl + .
|
2019-06-24 14:11:21 +02:00
|
|
|
// Reset platform
|
2020-12-01 00:57:57 +01:00
|
|
|
navigator.platform = "";
|
2018-05-15 12:40:07 +02:00
|
|
|
});
|
2017-03-13 21:41:28 +01:00
|
|
|
|
2020-07-15 01:29:15 +02:00
|
|
|
run_test("basic_chars", () => {
|
2017-03-10 22:24:54 +01:00
|
|
|
function process(s) {
|
2019-11-02 00:06:25 +01:00
|
|
|
const e = {
|
2017-03-10 22:24:54 +01:00
|
|
|
which: s.charCodeAt(0),
|
|
|
|
};
|
2017-03-18 22:05:07 +01:00
|
|
|
try {
|
|
|
|
return hotkey.process_keypress(e);
|
2020-10-07 10:20:41 +02:00
|
|
|
} catch (error) {
|
2017-03-18 22:05:07 +01:00
|
|
|
// An exception will be thrown here if a different
|
|
|
|
// function is called than the one declared. Try to
|
|
|
|
// provide a useful error message.
|
2017-11-09 16:26:38 +01:00
|
|
|
// add a newline to separate from other console output.
|
2017-03-18 22:05:07 +01:00
|
|
|
console.log('\nERROR: Mapping for character "' + e.which + '" does not match tests.');
|
2020-10-07 10:20:41 +02:00
|
|
|
throw error;
|
2017-03-18 22:05:07 +01:00
|
|
|
}
|
2017-03-10 22:24:54 +01:00
|
|
|
}
|
|
|
|
|
2021-02-11 01:23:23 +01:00
|
|
|
function assert_mapping(c, module, func_name, shiftKey) {
|
2021-02-13 03:46:14 +01:00
|
|
|
stubbing(module, func_name, (stub) => {
|
2017-03-10 22:24:54 +01:00
|
|
|
assert(process(c, shiftKey));
|
2021-02-13 03:46:14 +01:00
|
|
|
assert.equal(stub.num_calls, 1);
|
2017-03-10 22:24:54 +01:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function assert_unmapped(s) {
|
js: Automatically convert _.each to for…of.
This commit was automatically generated by the following script,
followed by lint --fix and a few small manual lint-related cleanups.
import * as babelParser from "recast/parsers/babel";
import * as recast from "recast";
import * as tsParser from "recast/parsers/typescript";
import { builders as b, namedTypes as n } from "ast-types";
import { Context } from "ast-types/lib/path-visitor";
import K from "ast-types/gen/kinds";
import { NodePath } from "ast-types/lib/node-path";
import assert from "assert";
import fs from "fs";
import path from "path";
import process from "process";
const checkExpression = (node: n.Node): node is K.ExpressionKind =>
n.Expression.check(node);
const checkStatement = (node: n.Node): node is K.StatementKind =>
n.Statement.check(node);
for (const file of process.argv.slice(2)) {
console.log("Parsing", file);
const ast = recast.parse(fs.readFileSync(file, { encoding: "utf8" }), {
parser: path.extname(file) === ".ts" ? tsParser : babelParser,
});
let changed = false;
let inLoop = false;
let replaceReturn = false;
const visitLoop = (...args: string[]) =>
function(this: Context, path: NodePath) {
for (const arg of args) {
this.visit(path.get(arg));
}
const old = { inLoop };
inLoop = true;
this.visit(path.get("body"));
inLoop = old.inLoop;
return false;
};
recast.visit(ast, {
visitDoWhileStatement: visitLoop("test"),
visitExpressionStatement(path) {
const { expression, comments } = path.node;
let valueOnly;
if (
n.CallExpression.check(expression) &&
n.MemberExpression.check(expression.callee) &&
!expression.callee.computed &&
n.Identifier.check(expression.callee.object) &&
expression.callee.object.name === "_" &&
n.Identifier.check(expression.callee.property) &&
["each", "forEach"].includes(expression.callee.property.name) &&
[2, 3].includes(expression.arguments.length) &&
checkExpression(expression.arguments[0]) &&
(n.FunctionExpression.check(expression.arguments[1]) ||
n.ArrowFunctionExpression.check(expression.arguments[1])) &&
[1, 2].includes(expression.arguments[1].params.length) &&
n.Identifier.check(expression.arguments[1].params[0]) &&
((valueOnly = expression.arguments[1].params[1] === undefined) ||
n.Identifier.check(expression.arguments[1].params[1])) &&
(expression.arguments[2] === undefined ||
n.ThisExpression.check(expression.arguments[2]))
) {
const old = { inLoop, replaceReturn };
inLoop = false;
replaceReturn = true;
this.visit(
path
.get("expression")
.get("arguments")
.get(1)
.get("body")
);
inLoop = old.inLoop;
replaceReturn = old.replaceReturn;
const [right, { body, params }] = expression.arguments;
const loop = b.forOfStatement(
b.variableDeclaration("let", [
b.variableDeclarator(
valueOnly ? params[0] : b.arrayPattern([params[1], params[0]])
),
]),
valueOnly
? right
: b.callExpression(
b.memberExpression(right, b.identifier("entries")),
[]
),
checkStatement(body) ? body : b.expressionStatement(body)
);
loop.comments = comments;
path.replace(loop);
changed = true;
}
this.traverse(path);
},
visitForStatement: visitLoop("init", "test", "update"),
visitForInStatement: visitLoop("left", "right"),
visitForOfStatement: visitLoop("left", "right"),
visitFunction(path) {
this.visit(path.get("params"));
const old = { replaceReturn };
replaceReturn = false;
this.visit(path.get("body"));
replaceReturn = old.replaceReturn;
return false;
},
visitReturnStatement(path) {
if (replaceReturn) {
assert(!inLoop); // could use labeled continue if this ever fires
const { argument, comments } = path.node;
if (argument === null) {
const s = b.continueStatement();
s.comments = comments;
path.replace(s);
} else {
const s = b.expressionStatement(argument);
s.comments = comments;
path.replace(s, b.continueStatement());
}
return false;
}
this.traverse(path);
},
visitWhileStatement: visitLoop("test"),
});
if (changed) {
console.log("Writing", file);
fs.writeFileSync(file, recast.print(ast).code, { encoding: "utf8" });
}
}
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-06 06:19:47 +01:00
|
|
|
for (const c of s) {
|
2017-03-10 22:24:54 +01:00
|
|
|
assert.equal(process(c), false);
|
js: Automatically convert _.each to for…of.
This commit was automatically generated by the following script,
followed by lint --fix and a few small manual lint-related cleanups.
import * as babelParser from "recast/parsers/babel";
import * as recast from "recast";
import * as tsParser from "recast/parsers/typescript";
import { builders as b, namedTypes as n } from "ast-types";
import { Context } from "ast-types/lib/path-visitor";
import K from "ast-types/gen/kinds";
import { NodePath } from "ast-types/lib/node-path";
import assert from "assert";
import fs from "fs";
import path from "path";
import process from "process";
const checkExpression = (node: n.Node): node is K.ExpressionKind =>
n.Expression.check(node);
const checkStatement = (node: n.Node): node is K.StatementKind =>
n.Statement.check(node);
for (const file of process.argv.slice(2)) {
console.log("Parsing", file);
const ast = recast.parse(fs.readFileSync(file, { encoding: "utf8" }), {
parser: path.extname(file) === ".ts" ? tsParser : babelParser,
});
let changed = false;
let inLoop = false;
let replaceReturn = false;
const visitLoop = (...args: string[]) =>
function(this: Context, path: NodePath) {
for (const arg of args) {
this.visit(path.get(arg));
}
const old = { inLoop };
inLoop = true;
this.visit(path.get("body"));
inLoop = old.inLoop;
return false;
};
recast.visit(ast, {
visitDoWhileStatement: visitLoop("test"),
visitExpressionStatement(path) {
const { expression, comments } = path.node;
let valueOnly;
if (
n.CallExpression.check(expression) &&
n.MemberExpression.check(expression.callee) &&
!expression.callee.computed &&
n.Identifier.check(expression.callee.object) &&
expression.callee.object.name === "_" &&
n.Identifier.check(expression.callee.property) &&
["each", "forEach"].includes(expression.callee.property.name) &&
[2, 3].includes(expression.arguments.length) &&
checkExpression(expression.arguments[0]) &&
(n.FunctionExpression.check(expression.arguments[1]) ||
n.ArrowFunctionExpression.check(expression.arguments[1])) &&
[1, 2].includes(expression.arguments[1].params.length) &&
n.Identifier.check(expression.arguments[1].params[0]) &&
((valueOnly = expression.arguments[1].params[1] === undefined) ||
n.Identifier.check(expression.arguments[1].params[1])) &&
(expression.arguments[2] === undefined ||
n.ThisExpression.check(expression.arguments[2]))
) {
const old = { inLoop, replaceReturn };
inLoop = false;
replaceReturn = true;
this.visit(
path
.get("expression")
.get("arguments")
.get(1)
.get("body")
);
inLoop = old.inLoop;
replaceReturn = old.replaceReturn;
const [right, { body, params }] = expression.arguments;
const loop = b.forOfStatement(
b.variableDeclaration("let", [
b.variableDeclarator(
valueOnly ? params[0] : b.arrayPattern([params[1], params[0]])
),
]),
valueOnly
? right
: b.callExpression(
b.memberExpression(right, b.identifier("entries")),
[]
),
checkStatement(body) ? body : b.expressionStatement(body)
);
loop.comments = comments;
path.replace(loop);
changed = true;
}
this.traverse(path);
},
visitForStatement: visitLoop("init", "test", "update"),
visitForInStatement: visitLoop("left", "right"),
visitForOfStatement: visitLoop("left", "right"),
visitFunction(path) {
this.visit(path.get("params"));
const old = { replaceReturn };
replaceReturn = false;
this.visit(path.get("body"));
replaceReturn = old.replaceReturn;
return false;
},
visitReturnStatement(path) {
if (replaceReturn) {
assert(!inLoop); // could use labeled continue if this ever fires
const { argument, comments } = path.node;
if (argument === null) {
const s = b.continueStatement();
s.comments = comments;
path.replace(s);
} else {
const s = b.expressionStatement(argument);
s.comments = comments;
path.replace(s, b.continueStatement());
}
return false;
}
this.traverse(path);
},
visitWhileStatement: visitLoop("test"),
});
if (changed) {
console.log("Writing", file);
fs.writeFileSync(file, recast.print(ast).code, { encoding: "utf8" });
}
}
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-06 06:19:47 +01:00
|
|
|
}
|
2017-03-10 22:24:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Unmapped keys should immediately return false, without
|
|
|
|
// calling any functions outside of hotkey.js.
|
2020-07-02 14:02:51 +02:00
|
|
|
assert_unmapped("abfmoyz");
|
2020-07-15 01:29:15 +02:00
|
|
|
assert_unmapped("BEFHILNOQTUWXYZ");
|
2017-03-10 22:24:54 +01:00
|
|
|
|
|
|
|
// We have to skip some checks due to the way the code is
|
|
|
|
// currently organized for mapped keys.
|
2020-01-29 20:22:07 +01:00
|
|
|
hotkey.in_content_editable_widget = return_false;
|
2017-05-27 15:40:54 +02:00
|
|
|
overlays.settings_open = return_false;
|
2017-03-10 22:24:54 +01:00
|
|
|
|
2021-02-11 01:23:23 +01:00
|
|
|
const popovers = set_global("popovers", {
|
2017-03-10 22:24:54 +01:00
|
|
|
actions_popped: return_false,
|
2018-06-12 12:29:34 +02:00
|
|
|
message_info_popped: return_false,
|
2020-07-09 16:59:01 +02:00
|
|
|
user_sidebar_popped: return_false,
|
2020-09-22 19:19:40 +02:00
|
|
|
user_info_popped: return_false,
|
2017-04-27 07:27:25 +02:00
|
|
|
});
|
2020-07-08 22:17:16 +02:00
|
|
|
set_global("stream_popover", {
|
|
|
|
stream_popped: return_false,
|
2020-07-09 03:18:27 +02:00
|
|
|
topic_popped: return_false,
|
2020-07-10 19:39:26 +02:00
|
|
|
all_messages_popped: return_false,
|
2020-07-10 20:25:24 +02:00
|
|
|
starred_messages_popped: return_false,
|
2020-07-08 22:17:16 +02:00
|
|
|
});
|
2021-02-10 04:53:22 +01:00
|
|
|
const emoji_picker = set_global("emoji_picker", {
|
2017-04-19 07:37:03 +02:00
|
|
|
reactions_popped: return_false,
|
2017-03-10 22:24:54 +01:00
|
|
|
});
|
2020-07-15 01:29:15 +02:00
|
|
|
set_global("hotspots", {
|
2017-08-02 04:46:56 +02:00
|
|
|
is_open: return_false,
|
|
|
|
});
|
2021-02-11 01:23:23 +01:00
|
|
|
const gear_menu = set_global("gear_menu", {
|
2020-02-03 21:13:55 +01:00
|
|
|
is_open: return_false,
|
|
|
|
});
|
2017-04-27 07:27:25 +02:00
|
|
|
|
2017-03-10 22:24:54 +01:00
|
|
|
// All letters should return false if we are composing text.
|
|
|
|
hotkey.processing_text = return_true;
|
|
|
|
|
|
|
|
function test_normal_typing() {
|
2020-07-15 01:29:15 +02:00
|
|
|
assert_unmapped("abcdefghijklmnopqrsuvwxyz");
|
|
|
|
assert_unmapped(" ");
|
|
|
|
assert_unmapped("[]\\.,;");
|
|
|
|
assert_unmapped("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
|
2017-09-07 03:01:17 +02:00
|
|
|
assert_unmapped('~!@#$%^*()_+{}:"<>');
|
2017-03-10 22:24:54 +01:00
|
|
|
}
|
|
|
|
|
js: Automatically convert _.each to for…of.
This commit was automatically generated by the following script,
followed by lint --fix and a few small manual lint-related cleanups.
import * as babelParser from "recast/parsers/babel";
import * as recast from "recast";
import * as tsParser from "recast/parsers/typescript";
import { builders as b, namedTypes as n } from "ast-types";
import { Context } from "ast-types/lib/path-visitor";
import K from "ast-types/gen/kinds";
import { NodePath } from "ast-types/lib/node-path";
import assert from "assert";
import fs from "fs";
import path from "path";
import process from "process";
const checkExpression = (node: n.Node): node is K.ExpressionKind =>
n.Expression.check(node);
const checkStatement = (node: n.Node): node is K.StatementKind =>
n.Statement.check(node);
for (const file of process.argv.slice(2)) {
console.log("Parsing", file);
const ast = recast.parse(fs.readFileSync(file, { encoding: "utf8" }), {
parser: path.extname(file) === ".ts" ? tsParser : babelParser,
});
let changed = false;
let inLoop = false;
let replaceReturn = false;
const visitLoop = (...args: string[]) =>
function(this: Context, path: NodePath) {
for (const arg of args) {
this.visit(path.get(arg));
}
const old = { inLoop };
inLoop = true;
this.visit(path.get("body"));
inLoop = old.inLoop;
return false;
};
recast.visit(ast, {
visitDoWhileStatement: visitLoop("test"),
visitExpressionStatement(path) {
const { expression, comments } = path.node;
let valueOnly;
if (
n.CallExpression.check(expression) &&
n.MemberExpression.check(expression.callee) &&
!expression.callee.computed &&
n.Identifier.check(expression.callee.object) &&
expression.callee.object.name === "_" &&
n.Identifier.check(expression.callee.property) &&
["each", "forEach"].includes(expression.callee.property.name) &&
[2, 3].includes(expression.arguments.length) &&
checkExpression(expression.arguments[0]) &&
(n.FunctionExpression.check(expression.arguments[1]) ||
n.ArrowFunctionExpression.check(expression.arguments[1])) &&
[1, 2].includes(expression.arguments[1].params.length) &&
n.Identifier.check(expression.arguments[1].params[0]) &&
((valueOnly = expression.arguments[1].params[1] === undefined) ||
n.Identifier.check(expression.arguments[1].params[1])) &&
(expression.arguments[2] === undefined ||
n.ThisExpression.check(expression.arguments[2]))
) {
const old = { inLoop, replaceReturn };
inLoop = false;
replaceReturn = true;
this.visit(
path
.get("expression")
.get("arguments")
.get(1)
.get("body")
);
inLoop = old.inLoop;
replaceReturn = old.replaceReturn;
const [right, { body, params }] = expression.arguments;
const loop = b.forOfStatement(
b.variableDeclaration("let", [
b.variableDeclarator(
valueOnly ? params[0] : b.arrayPattern([params[1], params[0]])
),
]),
valueOnly
? right
: b.callExpression(
b.memberExpression(right, b.identifier("entries")),
[]
),
checkStatement(body) ? body : b.expressionStatement(body)
);
loop.comments = comments;
path.replace(loop);
changed = true;
}
this.traverse(path);
},
visitForStatement: visitLoop("init", "test", "update"),
visitForInStatement: visitLoop("left", "right"),
visitForOfStatement: visitLoop("left", "right"),
visitFunction(path) {
this.visit(path.get("params"));
const old = { replaceReturn };
replaceReturn = false;
this.visit(path.get("body"));
replaceReturn = old.replaceReturn;
return false;
},
visitReturnStatement(path) {
if (replaceReturn) {
assert(!inLoop); // could use labeled continue if this ever fires
const { argument, comments } = path.node;
if (argument === null) {
const s = b.continueStatement();
s.comments = comments;
path.replace(s);
} else {
const s = b.expressionStatement(argument);
s.comments = comments;
path.replace(s, b.continueStatement());
}
return false;
}
this.traverse(path);
},
visitWhileStatement: visitLoop("test"),
});
if (changed) {
console.log("Writing", file);
fs.writeFileSync(file, recast.print(ast).code, { encoding: "utf8" });
}
}
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-06 06:19:47 +01:00
|
|
|
for (const settings_open of [return_true, return_false]) {
|
|
|
|
for (const is_active of [return_true, return_false]) {
|
|
|
|
for (const info_overlay_open of [return_true, return_false]) {
|
2021-02-10 04:53:22 +01:00
|
|
|
overlays = set_global("overlays", {
|
2020-07-20 22:18:43 +02:00
|
|
|
is_active,
|
|
|
|
settings_open,
|
|
|
|
info_overlay_open,
|
2020-07-02 14:02:51 +02:00
|
|
|
recent_topics_open: return_false,
|
2017-10-21 19:21:44 +02:00
|
|
|
});
|
2017-04-12 20:58:31 +02:00
|
|
|
test_normal_typing();
|
js: Automatically convert _.each to for…of.
This commit was automatically generated by the following script,
followed by lint --fix and a few small manual lint-related cleanups.
import * as babelParser from "recast/parsers/babel";
import * as recast from "recast";
import * as tsParser from "recast/parsers/typescript";
import { builders as b, namedTypes as n } from "ast-types";
import { Context } from "ast-types/lib/path-visitor";
import K from "ast-types/gen/kinds";
import { NodePath } from "ast-types/lib/node-path";
import assert from "assert";
import fs from "fs";
import path from "path";
import process from "process";
const checkExpression = (node: n.Node): node is K.ExpressionKind =>
n.Expression.check(node);
const checkStatement = (node: n.Node): node is K.StatementKind =>
n.Statement.check(node);
for (const file of process.argv.slice(2)) {
console.log("Parsing", file);
const ast = recast.parse(fs.readFileSync(file, { encoding: "utf8" }), {
parser: path.extname(file) === ".ts" ? tsParser : babelParser,
});
let changed = false;
let inLoop = false;
let replaceReturn = false;
const visitLoop = (...args: string[]) =>
function(this: Context, path: NodePath) {
for (const arg of args) {
this.visit(path.get(arg));
}
const old = { inLoop };
inLoop = true;
this.visit(path.get("body"));
inLoop = old.inLoop;
return false;
};
recast.visit(ast, {
visitDoWhileStatement: visitLoop("test"),
visitExpressionStatement(path) {
const { expression, comments } = path.node;
let valueOnly;
if (
n.CallExpression.check(expression) &&
n.MemberExpression.check(expression.callee) &&
!expression.callee.computed &&
n.Identifier.check(expression.callee.object) &&
expression.callee.object.name === "_" &&
n.Identifier.check(expression.callee.property) &&
["each", "forEach"].includes(expression.callee.property.name) &&
[2, 3].includes(expression.arguments.length) &&
checkExpression(expression.arguments[0]) &&
(n.FunctionExpression.check(expression.arguments[1]) ||
n.ArrowFunctionExpression.check(expression.arguments[1])) &&
[1, 2].includes(expression.arguments[1].params.length) &&
n.Identifier.check(expression.arguments[1].params[0]) &&
((valueOnly = expression.arguments[1].params[1] === undefined) ||
n.Identifier.check(expression.arguments[1].params[1])) &&
(expression.arguments[2] === undefined ||
n.ThisExpression.check(expression.arguments[2]))
) {
const old = { inLoop, replaceReturn };
inLoop = false;
replaceReturn = true;
this.visit(
path
.get("expression")
.get("arguments")
.get(1)
.get("body")
);
inLoop = old.inLoop;
replaceReturn = old.replaceReturn;
const [right, { body, params }] = expression.arguments;
const loop = b.forOfStatement(
b.variableDeclaration("let", [
b.variableDeclarator(
valueOnly ? params[0] : b.arrayPattern([params[1], params[0]])
),
]),
valueOnly
? right
: b.callExpression(
b.memberExpression(right, b.identifier("entries")),
[]
),
checkStatement(body) ? body : b.expressionStatement(body)
);
loop.comments = comments;
path.replace(loop);
changed = true;
}
this.traverse(path);
},
visitForStatement: visitLoop("init", "test", "update"),
visitForInStatement: visitLoop("left", "right"),
visitForOfStatement: visitLoop("left", "right"),
visitFunction(path) {
this.visit(path.get("params"));
const old = { replaceReturn };
replaceReturn = false;
this.visit(path.get("body"));
replaceReturn = old.replaceReturn;
return false;
},
visitReturnStatement(path) {
if (replaceReturn) {
assert(!inLoop); // could use labeled continue if this ever fires
const { argument, comments } = path.node;
if (argument === null) {
const s = b.continueStatement();
s.comments = comments;
path.replace(s);
} else {
const s = b.expressionStatement(argument);
s.comments = comments;
path.replace(s, b.continueStatement());
}
return false;
}
this.traverse(path);
},
visitWhileStatement: visitLoop("test"),
});
if (changed) {
console.log("Writing", file);
fs.writeFileSync(file, recast.print(ast).code, { encoding: "utf8" });
}
}
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-06 06:19:47 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-03-10 22:24:54 +01:00
|
|
|
|
|
|
|
// Ok, now test keys that work when we're viewing messages.
|
|
|
|
hotkey.processing_text = return_false;
|
2017-05-27 15:40:54 +02:00
|
|
|
overlays.settings_open = return_false;
|
2017-10-21 19:21:44 +02:00
|
|
|
overlays.streams_open = return_false;
|
|
|
|
overlays.lightbox_open = return_false;
|
|
|
|
overlays.drafts_open = return_false;
|
2020-04-08 13:59:56 +02:00
|
|
|
overlays.recent_topics = return_false;
|
2017-03-23 03:06:38 +01:00
|
|
|
|
2017-09-16 17:30:07 +02:00
|
|
|
page_params.can_create_streams = true;
|
2017-05-27 15:40:54 +02:00
|
|
|
overlays.streams_open = return_true;
|
|
|
|
overlays.is_active = return_true;
|
2021-02-11 01:23:23 +01:00
|
|
|
assert_mapping("S", subs, "keyboard_sub");
|
|
|
|
assert_mapping("V", subs, "view_stream");
|
|
|
|
assert_mapping("n", subs, "open_create_stream");
|
2017-09-16 17:30:07 +02:00
|
|
|
page_params.can_create_streams = false;
|
2020-07-15 01:29:15 +02:00
|
|
|
assert_unmapped("n");
|
2017-05-27 15:40:54 +02:00
|
|
|
overlays.streams_open = return_false;
|
2017-10-21 19:21:44 +02:00
|
|
|
test_normal_typing();
|
|
|
|
overlays.is_active = return_false;
|
2017-03-10 22:24:54 +01:00
|
|
|
|
2021-02-11 01:23:23 +01:00
|
|
|
assert_mapping("?", hashchange, "go_to_location");
|
|
|
|
assert_mapping("/", search, "initiate_search");
|
|
|
|
assert_mapping("w", activity, "initiate_search");
|
|
|
|
assert_mapping("q", stream_list, "initiate_search");
|
2017-03-10 22:24:54 +01:00
|
|
|
|
2021-02-11 01:23:23 +01:00
|
|
|
assert_mapping("A", narrow, "stream_cycle_backward");
|
|
|
|
assert_mapping("D", narrow, "stream_cycle_forward");
|
2017-03-10 22:24:54 +01:00
|
|
|
|
2021-02-11 01:23:23 +01:00
|
|
|
assert_mapping("c", compose_actions, "start");
|
|
|
|
assert_mapping("x", compose_actions, "start");
|
|
|
|
assert_mapping("P", narrow, "by");
|
|
|
|
assert_mapping("g", gear_menu, "open");
|
2017-10-03 00:41:43 +02:00
|
|
|
|
|
|
|
overlays.is_active = return_true;
|
|
|
|
overlays.drafts_open = return_true;
|
2021-02-11 01:23:23 +01:00
|
|
|
assert_mapping("d", overlays, "close_overlay");
|
2017-10-03 00:41:43 +02:00
|
|
|
overlays.drafts_open = return_false;
|
2017-10-21 19:21:44 +02:00
|
|
|
test_normal_typing();
|
2017-10-03 00:41:43 +02:00
|
|
|
overlays.is_active = return_false;
|
2021-02-11 01:23:23 +01:00
|
|
|
assert_mapping("d", drafts, "launch");
|
2017-03-10 22:24:54 +01:00
|
|
|
|
2020-08-11 01:47:54 +02:00
|
|
|
// Test opening and closing of recent topics
|
2020-04-08 13:59:56 +02:00
|
|
|
overlays.is_active = return_true;
|
|
|
|
overlays.recent_topics_open = return_true;
|
2021-02-11 01:23:23 +01:00
|
|
|
assert_mapping("t", overlays, "close_overlay");
|
2020-04-08 13:59:56 +02:00
|
|
|
overlays.recent_topics_open = return_false;
|
|
|
|
test_normal_typing();
|
|
|
|
overlays.is_active = return_false;
|
2021-02-11 01:23:23 +01:00
|
|
|
assert_mapping("t", hashchange, "go_to_location");
|
2020-04-08 13:59:56 +02:00
|
|
|
|
2017-03-10 22:24:54 +01:00
|
|
|
// Next, test keys that only work on a selected message.
|
2020-07-15 01:29:15 +02:00
|
|
|
const message_view_only_keys = "@+>RjJkKsSuvi:GM";
|
2017-03-23 19:38:08 +01:00
|
|
|
|
|
|
|
// Check that they do nothing without a selected message
|
2020-12-01 00:57:57 +01:00
|
|
|
current_msg_list.empty = return_true;
|
2017-03-23 19:38:08 +01:00
|
|
|
assert_unmapped(message_view_only_keys);
|
2017-03-10 22:24:54 +01:00
|
|
|
|
2020-12-01 00:57:57 +01:00
|
|
|
current_msg_list.empty = return_false;
|
2017-03-10 22:24:54 +01:00
|
|
|
|
2017-03-23 19:38:08 +01:00
|
|
|
// Check that they do nothing while in the settings overlay
|
2017-05-27 15:40:54 +02:00
|
|
|
overlays.settings_open = return_true;
|
2020-07-15 01:29:15 +02:00
|
|
|
assert_unmapped("@*+->rRjJkKsSuvi:GM");
|
2017-05-27 15:40:54 +02:00
|
|
|
overlays.settings_open = return_false;
|
2017-03-23 19:38:08 +01:00
|
|
|
|
|
|
|
// TODO: Similar check for being in the subs page
|
|
|
|
|
2021-02-11 01:23:23 +01:00
|
|
|
assert_mapping("@", compose_actions, "reply_with_mention");
|
|
|
|
assert_mapping("+", reactions, "toggle_emoji_reaction");
|
|
|
|
assert_mapping("-", condense, "toggle_collapse");
|
|
|
|
assert_mapping("r", compose_actions, "respond_to_message");
|
|
|
|
assert_mapping("R", compose_actions, "respond_to_message", true);
|
|
|
|
assert_mapping("j", navigate, "down");
|
|
|
|
assert_mapping("J", navigate, "page_down");
|
|
|
|
assert_mapping("k", navigate, "up");
|
|
|
|
assert_mapping("K", navigate, "page_up");
|
|
|
|
assert_mapping("s", narrow, "by_recipient");
|
|
|
|
assert_mapping("S", narrow, "by_topic");
|
|
|
|
assert_mapping("u", popovers, "show_sender_info");
|
|
|
|
assert_mapping("i", popovers, "open_message_menu");
|
|
|
|
assert_mapping(":", reactions, "open_reactions_popover", true);
|
|
|
|
assert_mapping(">", compose_actions, "quote_and_reply");
|
|
|
|
assert_mapping("e", message_edit, "start");
|
2017-10-02 23:10:55 +02:00
|
|
|
|
2017-10-21 19:21:44 +02:00
|
|
|
overlays.is_active = return_true;
|
|
|
|
overlays.lightbox_open = return_true;
|
2021-02-11 01:23:23 +01:00
|
|
|
assert_mapping("v", overlays, "close_overlay");
|
2017-10-21 19:21:44 +02:00
|
|
|
overlays.lightbox_open = return_false;
|
|
|
|
test_normal_typing();
|
|
|
|
overlays.is_active = return_false;
|
2021-02-11 01:23:23 +01:00
|
|
|
assert_mapping("v", lightbox, "show_from_selected_message");
|
2017-10-21 19:21:44 +02:00
|
|
|
|
2020-12-01 00:57:57 +01:00
|
|
|
emoji_picker.reactions_popped = return_true;
|
2021-02-11 01:23:23 +01:00
|
|
|
assert_mapping(":", emoji_picker, "navigate", true);
|
2020-12-01 00:57:57 +01:00
|
|
|
emoji_picker.reactions_popped = return_false;
|
2017-10-02 23:10:55 +02:00
|
|
|
|
2021-02-11 01:23:23 +01:00
|
|
|
assert_mapping("G", navigate, "to_end");
|
|
|
|
assert_mapping("M", muting_ui, "toggle_topic_mute");
|
2017-03-23 13:23:49 +01:00
|
|
|
|
|
|
|
// Test keys that work when a message is selected and
|
|
|
|
// also when the message list is empty.
|
2021-02-11 01:23:23 +01:00
|
|
|
assert_mapping("n", narrow, "narrow_to_next_topic");
|
|
|
|
assert_mapping("p", narrow, "narrow_to_next_pm_string");
|
2017-03-23 13:23:49 +01:00
|
|
|
|
2020-12-01 00:57:57 +01:00
|
|
|
current_msg_list.empty = return_true;
|
2021-02-11 01:23:23 +01:00
|
|
|
assert_mapping("n", narrow, "narrow_to_next_topic");
|
2020-12-01 00:57:57 +01:00
|
|
|
current_msg_list.empty = return_false;
|
2018-05-15 12:40:07 +02:00
|
|
|
});
|
2017-03-14 18:29:38 +01:00
|
|
|
|
2020-07-15 01:29:15 +02:00
|
|
|
run_test("motion_keys", () => {
|
2019-11-02 00:06:25 +01:00
|
|
|
const codes = {
|
2017-03-14 18:29:38 +01:00
|
|
|
down_arrow: 40,
|
|
|
|
end: 35,
|
|
|
|
home: 36,
|
|
|
|
left_arrow: 37,
|
2017-03-19 01:51:20 +01:00
|
|
|
right_arrow: 39,
|
2017-03-14 18:29:38 +01:00
|
|
|
page_up: 33,
|
|
|
|
page_down: 34,
|
|
|
|
spacebar: 32,
|
|
|
|
up_arrow: 38,
|
2020-07-15 01:29:15 +02:00
|
|
|
"+": 187,
|
2017-03-14 18:29:38 +01:00
|
|
|
};
|
|
|
|
|
2017-03-19 03:08:09 +01:00
|
|
|
function process(name, shiftKey, ctrlKey) {
|
2019-11-02 00:06:25 +01:00
|
|
|
const e = {
|
2017-03-14 18:29:38 +01:00
|
|
|
which: codes[name],
|
2020-07-20 22:18:43 +02:00
|
|
|
shiftKey,
|
|
|
|
ctrlKey,
|
2017-03-14 18:29:38 +01:00
|
|
|
};
|
2017-03-18 22:05:07 +01:00
|
|
|
|
|
|
|
try {
|
|
|
|
return hotkey.process_keydown(e);
|
2020-10-07 10:20:41 +02:00
|
|
|
} catch (error) {
|
2017-03-18 22:05:07 +01:00
|
|
|
// An exception will be thrown here if a different
|
|
|
|
// function is called than the one declared. Try to
|
|
|
|
// provide a useful error message.
|
2017-11-09 16:26:38 +01:00
|
|
|
// add a newline to separate from other console output.
|
2017-03-18 22:05:07 +01:00
|
|
|
console.log('\nERROR: Mapping for character "' + e.which + '" does not match tests.');
|
2020-10-07 10:20:41 +02:00
|
|
|
throw error;
|
2017-03-18 22:05:07 +01:00
|
|
|
}
|
2017-03-14 18:29:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
function assert_unmapped(name) {
|
|
|
|
assert.equal(process(name), false);
|
|
|
|
}
|
|
|
|
|
2021-02-11 01:23:23 +01:00
|
|
|
function assert_mapping(key_name, module, func_name, shiftKey, ctrlKey) {
|
2021-02-13 03:46:14 +01:00
|
|
|
stubbing(module, func_name, (stub) => {
|
2017-03-19 03:08:09 +01:00
|
|
|
assert(process(key_name, shiftKey, ctrlKey));
|
2021-02-13 03:46:14 +01:00
|
|
|
assert.equal(stub.num_calls, 1);
|
2017-03-14 18:29:38 +01:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-04-04 18:14:27 +02:00
|
|
|
list_util.inside_list = return_false;
|
2020-12-01 00:57:57 +01:00
|
|
|
current_msg_list.empty = return_true;
|
2017-05-27 15:40:54 +02:00
|
|
|
overlays.settings_open = return_false;
|
|
|
|
overlays.streams_open = return_false;
|
|
|
|
overlays.lightbox_open = return_false;
|
2017-03-14 18:29:38 +01:00
|
|
|
|
2020-07-15 01:29:15 +02:00
|
|
|
assert_unmapped("down_arrow");
|
|
|
|
assert_unmapped("end");
|
|
|
|
assert_unmapped("home");
|
|
|
|
assert_unmapped("page_up");
|
|
|
|
assert_unmapped("page_down");
|
|
|
|
assert_unmapped("spacebar");
|
|
|
|
assert_unmapped("up_arrow");
|
2017-03-14 18:29:38 +01:00
|
|
|
|
2020-12-01 00:57:57 +01:00
|
|
|
list_util.inside_list = return_true;
|
2021-02-11 01:23:23 +01:00
|
|
|
assert_mapping("up_arrow", list_util, "go_up");
|
|
|
|
assert_mapping("down_arrow", list_util, "go_down");
|
2017-04-04 18:14:27 +02:00
|
|
|
list_util.inside_list = return_false;
|
|
|
|
|
2020-12-01 00:57:57 +01:00
|
|
|
current_msg_list.empty = return_false;
|
2021-02-11 01:23:23 +01:00
|
|
|
assert_mapping("down_arrow", navigate, "down");
|
|
|
|
assert_mapping("end", navigate, "to_end");
|
|
|
|
assert_mapping("home", navigate, "to_home");
|
|
|
|
assert_mapping("left_arrow", message_edit, "edit_last_sent_message");
|
|
|
|
assert_mapping("page_up", navigate, "page_up");
|
|
|
|
assert_mapping("page_down", navigate, "page_down");
|
|
|
|
assert_mapping("spacebar", navigate, "page_down");
|
|
|
|
assert_mapping("up_arrow", navigate, "up");
|
2017-03-14 18:29:38 +01:00
|
|
|
|
2017-05-27 15:40:54 +02:00
|
|
|
overlays.info_overlay_open = return_true;
|
2020-07-15 01:29:15 +02:00
|
|
|
assert_unmapped("down_arrow");
|
|
|
|
assert_unmapped("up_arrow");
|
2017-05-27 15:40:54 +02:00
|
|
|
overlays.info_overlay_open = return_false;
|
2017-04-12 20:58:31 +02:00
|
|
|
|
2017-05-27 15:40:54 +02:00
|
|
|
overlays.streams_open = return_true;
|
2021-02-11 01:23:23 +01:00
|
|
|
assert_mapping("up_arrow", subs, "switch_rows");
|
|
|
|
assert_mapping("down_arrow", subs, "switch_rows");
|
2017-05-27 15:40:54 +02:00
|
|
|
overlays.streams_open = return_false;
|
2017-03-23 06:02:01 +01:00
|
|
|
|
2017-05-27 15:40:54 +02:00
|
|
|
overlays.lightbox_open = return_true;
|
2021-02-11 01:23:23 +01:00
|
|
|
assert_mapping("left_arrow", lightbox, "prev");
|
|
|
|
assert_mapping("right_arrow", lightbox, "next");
|
2017-05-27 15:40:54 +02:00
|
|
|
overlays.lightbox_open = return_false;
|
2017-03-22 02:49:52 +01:00
|
|
|
|
2020-01-29 20:22:07 +01:00
|
|
|
hotkey.in_content_editable_widget = return_true;
|
2020-07-15 01:29:15 +02:00
|
|
|
assert_unmapped("down_arrow");
|
|
|
|
assert_unmapped("up_arrow");
|
2020-01-29 20:22:07 +01:00
|
|
|
hotkey.in_content_editable_widget = return_false;
|
2017-04-04 19:59:04 +02:00
|
|
|
|
2017-05-27 15:40:54 +02:00
|
|
|
overlays.settings_open = return_true;
|
2020-07-15 01:29:15 +02:00
|
|
|
assert_unmapped("end");
|
|
|
|
assert_unmapped("home");
|
|
|
|
assert_unmapped("left_arrow");
|
|
|
|
assert_unmapped("page_up");
|
|
|
|
assert_unmapped("page_down");
|
|
|
|
assert_unmapped("spacebar");
|
2017-05-27 15:40:54 +02:00
|
|
|
overlays.settings_open = return_false;
|
2017-04-04 20:48:08 +02:00
|
|
|
|
2017-10-03 00:41:43 +02:00
|
|
|
overlays.is_active = return_true;
|
|
|
|
overlays.drafts_open = return_true;
|
2021-02-11 01:23:23 +01:00
|
|
|
assert_mapping("up_arrow", drafts, "drafts_handle_events");
|
|
|
|
assert_mapping("down_arrow", drafts, "drafts_handle_events");
|
2017-10-03 00:41:43 +02:00
|
|
|
overlays.is_active = return_false;
|
|
|
|
overlays.drafts_open = return_false;
|
2018-05-15 12:40:07 +02:00
|
|
|
});
|