Files
upstream-zulip/web/tests/widgetize.test.cjs
upstream-mirror 64898b2c79
Some checks failed
Code scanning / CodeQL (push) Failing after 15s
Zulip production suite / Ubuntu 22.04 production build (push) Failing after 26s
Zulip production suite / Debian 12 production install with custom db name and user (push) Has been skipped
Zulip production suite / Ubuntu 22.04 production install and PostgreSQL upgrade with pgroonga (push) Has been skipped
Zulip production suite / Ubuntu 24.04 production install (push) Has been skipped
Zulip production suite / Ubuntu 26.04 production install (push) Has been skipped
Zulip production suite / Debian 13 production install (push) Has been skipped
Zulip production suite / 7.0 Version Upgrade (push) Has been skipped
Zulip production suite / 8.0 Version Upgrade (push) Has been skipped
Zulip production suite / 6.0 Version Upgrade (push) Has been skipped
Zulip production suite / 10.0 Version Upgrade (push) Has been skipped
Zulip production suite / 9.0 Version Upgrade (push) Has been skipped
Zulip production suite / 12.0 Version Upgrade (push) Has been skipped
Zulip production suite / 11.0 Version Upgrade (push) Has been skipped
GitHub Actions Security Analysis with zizmor / zizmor (push) Failing after 3s
Zulip CI / Debian 12 (Python 3.11, backend + documentation) (push) Failing after 26s
Zulip CI / Ubuntu 22.04 (Python 3.10, backend + frontend) (push) Failing after 3s
Zulip CI / Ubuntu 24.04 (Python 3.12, backend) (push) Failing after 25s
Zulip CI / Ubuntu 26.04 (Python 3.14, backend) (push) Failing after 25s
Zulip CI / Debian 13 (Python 3.13, backend) (push) Failing after 28s
Zulip production suite / Required jobs (push) Has been cancelled
Zulip CI / Required jobs (push) Has been cancelled
API Documentation Update Check / check-feature-level-updated (push) Has been cancelled
API Documentation Update Check / notify-if-api-docs-changed (push) Has been cancelled
snapshot of https://github.com/zulip/zulip.git @ 48c69911c7dd4e03b20552eb3bd77ad8151c1357 (2026-09-15)
2026-09-15 15:05:30 +05:00

283 lines
7.5 KiB
JavaScript

"use strict";
const assert = require("node:assert/strict");
const {mock_esm, set_global, zrequire} = require("./lib/namespace.cjs");
const {run_test} = require("./lib/test.cjs");
const blueslip = require("./lib/zblueslip.cjs");
const {$} = require("./lib/zjquery.cjs");
const sample_events = [
{
data: {
option: "First option",
idx: 1,
type: "new_option",
},
sender_id: 101,
},
{
data: {
option: "Second option",
idx: 1,
type: "new_option",
},
sender_id: 102,
},
{
data: {
option: "Third option",
idx: 1,
type: "new_option",
},
sender_id: 102,
},
];
let events;
let $widget_elem;
let is_event_handled;
let is_widget_activated;
let is_widget_rendered;
const fake_poll_widget = {
activate(data) {
is_widget_activated = true;
const inbound_events_handler = (e) => {
is_event_handled = true;
assert.deepStrictEqual(e, events);
};
const widget_data = {
widget_type: "poll",
extra_data: data.any_data.extra_data,
};
return {inbound_events_handler, widget_data};
},
render(data) {
is_widget_rendered = true;
$widget_elem = data.$elem;
assert.ok($widget_elem.hasClass("widget-content"));
data.callback("test_data");
},
};
const message_lists = mock_esm("../src/message_lists", {current: {id: 2}, home: {id: 1}});
mock_esm("../src/poll_widget", fake_poll_widget);
set_global("document", "document-stub");
const {GenericWidget} = zrequire("generic_widget");
const widgetize = zrequire("widgetize");
const widgets = zrequire("widgets");
widgets.initialize();
function test(label, f) {
run_test(label, ({override}) => {
events = [...sample_events];
$widget_elem = undefined;
is_event_handled = false;
is_widget_activated = false;
is_widget_rendered = false;
widgetize.clear_for_testing();
f({override});
});
}
test("activate", ({override}) => {
// Both widgetize.render and widgetize.handle_event are tested
// here to use the "caching" of widgets.
const $row = $.create("<stub message row>");
$row.attr("id", `message-row-${message_lists.current.id}-2909`);
const $message_content = $.create(`#message-row-${message_lists.current.id}-2909`);
$row.set_find_results(".message_content", $message_content);
const $widget_content = $.create(".widget-content");
$widget_content.addClass("widget-content");
$row.set_find_results(".widget-content", $widget_content);
let is_widget_elem_inserted;
let inserted_element;
$message_content[0].append = (element) => {
is_widget_elem_inserted = true;
inserted_element = element;
assert.ok(element.classList.contains("widget-content"));
};
const activate_opts = {
events: [...events],
any_data: {
widget_type: "poll",
extra_data: "",
},
message: {
id: 2001,
},
};
// Test widget initialization
is_widget_elem_inserted = false;
is_widget_activated = false;
is_widget_rendered = false;
assert.deepEqual(widgetize.get_message_ids(), []);
widgetize.activate(activate_opts);
// activate() should create widget and handle events, but NOT render
assert.ok(is_widget_activated);
assert.ok(!is_widget_rendered);
assert.ok(!is_widget_elem_inserted);
assert.deepEqual(widgetize.get_message_ids(), [activate_opts.message.id]);
// Activate with invalid widget type
blueslip.expect("warn", "unknown widget_type");
is_widget_activated = false;
activate_opts.any_data.widget_type = "invalid_widget";
activate_opts.message.id = 2002;
widgetize.activate(activate_opts);
assert.ok(!is_widget_activated);
assert.deepEqual(blueslip.get_test_logs("warn")[0].more_info, {widget_type: "invalid_widget"});
// Activate with tictactoe (legacy widget) should silently fail
is_widget_activated = false;
activate_opts.any_data.widget_type = "tictactoe";
activate_opts.message.id = 2003;
widgetize.activate(activate_opts);
assert.ok(!is_widget_activated);
// Test widget UI rendering
widgetize.clear_for_testing();
is_widget_elem_inserted = false;
is_widget_activated = false;
is_widget_rendered = false;
events = [...sample_events];
activate_opts.any_data.widget_type = "poll";
activate_opts.events = [...events];
activate_opts.message.id = 2005;
widgetize.activate(activate_opts);
assert.ok(is_widget_activated);
assert.ok(!is_widget_rendered);
assert.ok(!is_widget_elem_inserted);
const render_opts = {
post_to_server(data) {
assert.equal(data.msg_type, "widget");
assert.equal(data.data, "test_data");
},
$row,
message: {
id: 2005,
},
};
widgetize.render(render_opts);
assert.ok(is_widget_rendered);
assert.ok(is_widget_elem_inserted);
assert.equal(inserted_element, $widget_elem[0]);
// Test render without a widget should return early
is_widget_rendered = false;
is_widget_elem_inserted = false;
render_opts.message.id = 9999;
widgetize.render(render_opts);
assert.ok(!is_widget_rendered);
assert.ok(!is_widget_elem_inserted);
// Test incoming widget events
const $empty_row = $.set_results("<empty row>", []);
let expected_message_id;
const post_activate_event = {
data: {
idx: 1,
type: "new_option",
},
message: {
id: 2001,
},
post_to_server(data) {
assert.equal(data.msg_type, "widget");
assert.equal(data.data, "test_data");
},
sender_id: 102,
};
const handle_events = (e) => {
is_event_handled = true;
assert.deepEqual(e, [post_activate_event]);
};
// handle_event on message not in view should only update the state
message_lists.current = undefined;
is_event_handled = false;
is_widget_rendered = false;
expected_message_id = 2001;
const widget_data = {widget_type: "poll", extra_data: ""};
widgetize.set_widget_for_tests(2001, new GenericWidget(handle_events, widget_data));
widgetize.handle_event(post_activate_event);
assert.ok(is_event_handled);
assert.ok(!is_widget_rendered);
message_lists.current = {id: 2};
override(message_lists.current, "get_row", (idx) => {
assert.equal(idx, expected_message_id);
if (idx === 2001) {
return $row;
}
return $empty_row;
});
// Test handle_event for ui update
widgetize.set_widget_for_tests(2001, new GenericWidget(handle_events, widget_data));
is_event_handled = false;
is_widget_rendered = false;
expected_message_id = 2001;
widgetize.handle_event(post_activate_event);
assert.ok(is_event_handled);
assert.ok(is_widget_rendered);
// Test handle_event for nonexistent widget
is_event_handled = false;
is_widget_rendered = false;
expected_message_id = 1000;
const nonexistent_event = {
data: {
idx: 1,
type: "new_option",
},
sender_id: 102,
post_to_server() {},
message: {
id: 1000,
},
};
widgetize.handle_event(nonexistent_event);
assert.ok(!is_event_handled);
assert.ok(!is_widget_rendered);
});