feat(housekeeping): load complete poll operator data
This commit is contained in:
1 parent
de94b47cae
commit
dba58cad4f
2 files changed
+405
-2
No files matched your search
@@ -280,6 +280,218 @@ describe("Content query", () => {
|
||||
},
|
||||
});
|
||||
});
|
||||
it("loads bounded poll summaries with operator counts and bound filters", async () => {
|
||||
queryMocks.execute
|
||||
.mockResolvedValueOnce([[{ total: 1 }]])
|
||||
.mockResolvedValueOnce([
|
||||
[
|
||||
{
|
||||
id: 7,
|
||||
title: "Autumn plans",
|
||||
status: "active",
|
||||
updated_at: new Date("2026-09-01T08:00:00.000Z"),
|
||||
show_results: 1,
|
||||
multiple_choice: 0,
|
||||
starts_at: new Date("2026-09-02T18:00:00.000Z"),
|
||||
ends_at: null,
|
||||
question_count: 3,
|
||||
voter_count: 12,
|
||||
answer_count: 30,
|
||||
},
|
||||
],
|
||||
]);
|
||||
|
||||
const result = await loadProductionContentQuery({
|
||||
routeId: "content.engagement.polls",
|
||||
params: {},
|
||||
list: {
|
||||
...normalizedResponsePage,
|
||||
search: "Autumn",
|
||||
status: "active",
|
||||
pageSize: 25,
|
||||
offset: 0,
|
||||
},
|
||||
});
|
||||
|
||||
expect(result.items[0]?.privatePayload).toEqual({
|
||||
kind: "poll-summary",
|
||||
showResults: true,
|
||||
multipleChoice: false,
|
||||
startsAt: "2026-09-02T18:00:00.000Z",
|
||||
endsAt: null,
|
||||
questionCount: 3,
|
||||
voterCount: 12,
|
||||
answerCount: 30,
|
||||
});
|
||||
const sql = JSON.stringify(queryMocks.execute.mock.calls);
|
||||
expect(sql).toContain("%autumn%");
|
||||
expect(sql).toContain("active");
|
||||
});
|
||||
|
||||
it("returns the stable poll-create payload without database access", async () => {
|
||||
const result = await loadProductionContentQuery({
|
||||
routeId: "content.engagement.poll-create",
|
||||
params: {},
|
||||
list: { ...normalizedResponsePage, search: "", pageSize: 25, offset: 0 },
|
||||
});
|
||||
|
||||
expect(result).toEqual({
|
||||
kind: "engagement",
|
||||
items: [
|
||||
{
|
||||
id: "create",
|
||||
title: "Create poll",
|
||||
href: "/ase-next/content/engagement/polls/create",
|
||||
privatePayload: { kind: "poll-create" },
|
||||
},
|
||||
],
|
||||
total: 1,
|
||||
partialDependencies: [],
|
||||
});
|
||||
expect(queryMocks.execute).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("loads selected poll results from bounded grouped aggregates and response pages", async () => {
|
||||
queryMocks.execute
|
||||
.mockResolvedValueOnce([
|
||||
[
|
||||
{
|
||||
id: 7,
|
||||
title: "Autumn plans",
|
||||
description: "Complete poll",
|
||||
status: "active",
|
||||
updated_at: new Date("2026-09-01T08:00:00.000Z"),
|
||||
show_results: 1,
|
||||
multiple_choice: 0,
|
||||
starts_at: new Date("2026-09-02T18:00:00.000Z"),
|
||||
ends_at: null,
|
||||
question_count: 2,
|
||||
voter_count: 12,
|
||||
answer_count: 30,
|
||||
},
|
||||
],
|
||||
])
|
||||
.mockResolvedValueOnce([
|
||||
[
|
||||
{
|
||||
id: 21,
|
||||
question: "Favourite colour?",
|
||||
type: "single",
|
||||
sort_order: 0,
|
||||
options: "Red\nBlue",
|
||||
},
|
||||
{
|
||||
id: 22,
|
||||
question: "What should improve?",
|
||||
type: "text",
|
||||
sort_order: 1,
|
||||
options: "",
|
||||
},
|
||||
],
|
||||
])
|
||||
.mockResolvedValueOnce([
|
||||
[
|
||||
{ question_id: 21, answer: "Red", answer_count: 3 },
|
||||
{ question_id: 21, answer: "Blue", answer_count: 1 },
|
||||
],
|
||||
])
|
||||
.mockResolvedValueOnce([[{ total: 51 }]])
|
||||
.mockResolvedValueOnce([
|
||||
[
|
||||
{
|
||||
id: 1,
|
||||
question_id: 22,
|
||||
user_id: 9,
|
||||
username: "Alice",
|
||||
answer: "More events",
|
||||
created_at: new Date("2026-09-02T20:00:00.000Z"),
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
question_id: 22,
|
||||
user_id: 10,
|
||||
username: null,
|
||||
answer: "Better prizes",
|
||||
created_at: new Date("2026-09-02T19:00:00.000Z"),
|
||||
},
|
||||
],
|
||||
]);
|
||||
|
||||
const result = await loadProductionContentQuery({
|
||||
routeId: "content.engagement.poll-detail",
|
||||
params: { id: "7" },
|
||||
list: {
|
||||
...normalizedResponsePage,
|
||||
search: "",
|
||||
pageSize: 25,
|
||||
offset: 0,
|
||||
responseQuestionId: "22",
|
||||
responsePageSize: 25,
|
||||
responseOffset: 25,
|
||||
},
|
||||
});
|
||||
|
||||
expect(result.items[0]?.privatePayload).toMatchObject({
|
||||
kind: "poll-detail",
|
||||
questions: [
|
||||
{
|
||||
id: "21",
|
||||
options: ["Red", "Blue"],
|
||||
answerCount: 4,
|
||||
choiceResults: [
|
||||
{ option: "Red", count: 3 },
|
||||
{ option: "Blue", count: 1 },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "22",
|
||||
type: "text",
|
||||
options: [],
|
||||
answerCount: 0,
|
||||
choiceResults: [],
|
||||
},
|
||||
],
|
||||
textResponses: {
|
||||
questionId: "22",
|
||||
total: 51,
|
||||
pageSize: 25,
|
||||
offset: 25,
|
||||
items: [
|
||||
{ userId: "9", username: "Alice", answer: "More events" },
|
||||
{ userId: "10", username: null, answer: "Better prizes" },
|
||||
],
|
||||
},
|
||||
});
|
||||
const sql = JSON.stringify(queryMocks.execute.mock.calls);
|
||||
expect(sql).toContain("LIMIT 101");
|
||||
expect(sql).toContain("LIMIT 10001");
|
||||
expect(sql).toContain("7");
|
||||
expect(sql).toContain("22");
|
||||
expect(sql).toContain("25");
|
||||
expect(queryMocks.execute).toHaveBeenCalledTimes(5);
|
||||
});
|
||||
|
||||
it("returns a valid empty detail result when the selected poll is missing", async () => {
|
||||
queryMocks.execute.mockResolvedValueOnce([[]]);
|
||||
|
||||
await expect(
|
||||
loadProductionContentQuery({
|
||||
routeId: "content.engagement.poll-detail",
|
||||
params: { id: "7" },
|
||||
list: {
|
||||
...normalizedResponsePage,
|
||||
search: "",
|
||||
pageSize: 25,
|
||||
offset: 0,
|
||||
},
|
||||
}),
|
||||
).resolves.toEqual({
|
||||
kind: "engagement",
|
||||
items: [],
|
||||
total: 0,
|
||||
partialDependencies: [],
|
||||
});
|
||||
});
|
||||
|
||||
it("loads only the selected event with all related operator data", async () => {
|
||||
queryMocks.execute
|
||||
|
||||
Reference in new issue
Block a user