discourse/plugins/discourse-ai/test/javascripts/unit/services/ai-conversations-sidebar-manager-test.js
Sam 82e463c99f
FEATURE: Star AI bot conversations in sidebar (#39869)
Adds an experimental "Starred" section to the AI bot conversation
sidebar. Users can star up to 200 conversations they own; starred
items appear in a dedicated section above the time-bucketed list and
are skipped from the regular pagination.

Introduces:

- `discourse_ai_ai_bot_conversation_stars` table and
  `DiscourseAi::AiBot::ConversationStar` model
- `ListConversations` and `UpdateConversationStar` services backing
  the existing `conversations#index` and a new
  `PUT /ai-bot/conversations/:topic_id/starred` endpoint
- Sidebar context menu component plus updates to the sidebar
  manager to render and toggle starred state

The feature is gated by the hidden, experimental
`enable_ai_bot_starred_conversations` upcoming change setting and is
off by default.


<img width="1216" height="537" alt="image"
src="https://github.com/user-attachments/assets/6c7d15bb-8b7c-48d9-9f02-f449764e63ff"
/>

<img width="955" height="648" alt="image"
src="https://github.com/user-attachments/assets/0f87bd8e-e43e-483d-bf68-886cbfb09eea"
/>

---------

Co-authored-by: discourse-patch-triage[bot] <272280883+discourse-patch-triage[bot]@users.noreply.github.com>
2026-05-14 15:04:31 +10:00

84 lines
2.6 KiB
JavaScript
Vendored

import { getOwner } from "@ember/owner";
import { setupTest } from "ember-qunit";
import { module, test } from "qunit";
import { AI_CONVERSATIONS_PANEL } from "discourse/plugins/discourse-ai/discourse/services/ai-conversations-sidebar-manager";
module("Unit | Service | ai-conversations-sidebar-manager", function (hooks) {
setupTest(hooks);
test("unstarred conversations move into newly created date sections", function (assert) {
const service = getOwner(this).lookup(
"service:ai-conversations-sidebar-manager"
);
let setPanelCount = 0;
const registeredSections = [];
service.api = {
addSidebarSection(callback, panel) {
registeredSections.push({ callback, panel });
},
};
Object.defineProperty(service.sidebarState, "currentPanel", {
configurable: true,
value: { key: AI_CONVERSATIONS_PANEL },
});
service.sidebarState.setPanel = (panel) => {
setPanelCount += 1;
assert.strictEqual(panel, AI_CONVERSATIONS_PANEL);
};
service.siteSettings.enable_ai_bot_starred_conversations = true;
service.capabilities.isIpadOS = false;
const lastPostedAt = new Date(Date.now() - 3 * 86400000).toISOString();
const topic = {
id: 1,
slug: "starred-topic",
title: "Starred topic",
ai_conversation_starred: true,
ai_conversation_starred_at: new Date().toISOString(),
last_posted_at: lastPostedAt,
};
service.topics = [topic];
service._rebuildSections();
assert.false(
service.sections.some((section) => section.name === "last-7-days"),
"starred-only topics do not create date sections"
);
const setPanelCountBeforeUnstar = setPanelCount;
service._updateTopic({
...topic,
ai_conversation_starred: false,
ai_conversation_starred_at: null,
});
const lastSevenDaysSection = service.sections.find(
(section) => section.name === "last-7-days"
);
assert.strictEqual(
lastSevenDaysSection?.links.length,
1,
"the unstarred conversation appears in its date section"
);
assert.strictEqual(
lastSevenDaysSection.links[0].key,
topic.id,
"the date section contains the unstarred topic"
);
assert.true(
registeredSections.some(
(registeredSection) =>
registeredSection.panel === AI_CONVERSATIONS_PANEL
),
"the new section is registered with the AI conversations panel"
);
assert.true(
setPanelCount > setPanelCountBeforeUnstar,
"the sidebar panel is refreshed after registering the new section"
);
});
});