discourse/test/javascripts/models/topic-tracking-state-test.js
Sam Saffron eb18f91cf7
DEV: new api to iterate through tracked topics
`topicTrackingState.forEachTracked(topic,isNew,isUnread)` can be used to
iterate through tracking state efficiently.

This is handy for extension looking at subsets of tags and categories.
2020-08-04 10:40:03 +10:00

347 lines
8.1 KiB
JavaScript

import TopicTrackingState from "discourse/models/topic-tracking-state";
import createStore from "helpers/create-store";
import Category from "discourse/models/category";
import { NotificationLevels } from "discourse/lib/notification-levels";
import User from "discourse/models/user";
QUnit.module("model:topic-tracking-state", {
beforeEach() {
this.clock = sinon.useFakeTimers(new Date(2012, 11, 31, 12, 0).getTime());
},
afterEach() {
this.clock.restore();
}
});
QUnit.test("tag counts", function(assert) {
const state = TopicTrackingState.create();
state.loadStates([
{
topic_id: 1,
last_read_post_number: null,
tags: ["foo", "new"]
},
{
topic_id: 2,
last_read_post_number: null,
tags: ["new"]
},
{
topic_id: 3,
last_read_post_number: null,
tags: ["random"]
},
{
topic_id: 4,
last_read_post_number: 1,
highest_post_number: 7,
tags: ["unread"],
notification_level: NotificationLevels.TRACKING
},
{
topic_id: 5,
last_read_post_number: 1,
highest_post_number: 7,
tags: ["bar", "unread"],
notification_level: NotificationLevels.TRACKING
},
{
topic_id: 6,
last_read_post_number: 1,
highest_post_number: 7,
tags: null,
notification_level: NotificationLevels.TRACKING
}
]);
const states = state.countTags(["new", "unread"]);
assert.equal(states["new"].newCount, 2, "new counts");
assert.equal(states["new"].unreadCount, 0, "new counts");
assert.equal(states["unread"].unreadCount, 2, "unread counts");
assert.equal(states["unread"].newCount, 0, "unread counts");
});
QUnit.test("forEachTracked", function(assert) {
const state = TopicTrackingState.create();
state.loadStates([
{
topic_id: 1,
last_read_post_number: null,
tags: ["foo", "new"]
},
{
topic_id: 2,
last_read_post_number: null,
tags: ["new"]
},
{
topic_id: 3,
last_read_post_number: null,
tags: ["random"]
},
{
topic_id: 4,
last_read_post_number: 1,
highest_post_number: 7,
category_id: 7,
tags: ["unread"],
notification_level: NotificationLevels.TRACKING
},
{
topic_id: 5,
last_read_post_number: 1,
highest_post_number: 7,
tags: ["bar", "unread"],
category_id: 7,
notification_level: NotificationLevels.TRACKING
},
{
topic_id: 6,
last_read_post_number: 1,
highest_post_number: 7,
tags: null,
notification_level: NotificationLevels.TRACKING
}
]);
let randomUnread = 0,
randomNew = 0,
sevenUnread = 0,
sevenNew = 0;
state.forEachTracked((topic, isNew, isUnread) => {
if (topic.category_id === 7) {
if (isNew) {
sevenNew += 1;
}
if (isUnread) {
sevenUnread += 1;
}
}
if (topic.tags && topic.tags.indexOf("random") > -1) {
if (isNew) {
randomNew += 1;
}
if (isUnread) {
randomUnread += 1;
}
}
});
assert.equal(randomNew, 1, "random new");
assert.equal(randomUnread, 0, "random unread");
assert.equal(sevenNew, 0, "seven unread");
assert.equal(sevenUnread, 2, "seven unread");
});
QUnit.test("sync", function(assert) {
const state = TopicTrackingState.create();
state.states["t111"] = { last_read_post_number: null };
state.updateSeen(111, 7);
const list = {
topics: [
{
highest_post_number: null,
id: 111,
unread: 10,
new_posts: 10
}
]
};
state.sync(list, "new");
assert.equal(
list.topics.length,
0,
"expect new topic to be removed as it was seen"
);
});
QUnit.test("subscribe to category", function(assert) {
const store = createStore();
const darth = store.createRecord("category", { id: 1, slug: "darth" }),
luke = store.createRecord("category", {
id: 2,
slug: "luke",
parentCategory: darth
}),
categoryList = [darth, luke];
sandbox.stub(Category, "list").returns(categoryList);
const state = TopicTrackingState.create();
state.trackIncoming("c/darth/1/l/latest");
state.notify({
message_type: "new_topic",
topic_id: 1,
payload: { category_id: 2, topic_id: 1 }
});
state.notify({
message_type: "new_topic",
topic_id: 2,
payload: { category_id: 3, topic_id: 2 }
});
state.notify({
message_type: "new_topic",
topic_id: 3,
payload: { category_id: 1, topic_id: 3 }
});
assert.equal(
state.get("incomingCount"),
2,
"expect to properly track incoming for category"
);
state.resetTracking();
state.trackIncoming("c/darth/luke/2/l/latest");
state.notify({
message_type: "new_topic",
topic_id: 1,
payload: { category_id: 2, topic_id: 1 }
});
state.notify({
message_type: "new_topic",
topic_id: 2,
payload: { category_id: 3, topic_id: 2 }
});
state.notify({
message_type: "new_topic",
topic_id: 3,
payload: { category_id: 1, topic_id: 3 }
});
assert.equal(
state.get("incomingCount"),
1,
"expect to properly track incoming for subcategory"
);
});
QUnit.test("getSubCategoryIds", assert => {
const store = createStore();
const foo = store.createRecord("category", { id: 1, slug: "foo" });
const bar = store.createRecord("category", {
id: 2,
slug: "bar",
parent_category_id: foo.id
});
const baz = store.createRecord("category", {
id: 3,
slug: "baz",
parent_category_id: bar.id
});
sandbox.stub(Category, "list").returns([foo, bar, baz]);
const state = TopicTrackingState.create();
assert.deepEqual(Array.from(state.getSubCategoryIds(1)), [1, 2, 3]);
assert.deepEqual(Array.from(state.getSubCategoryIds(2)), [2, 3]);
assert.deepEqual(Array.from(state.getSubCategoryIds(3)), [3]);
});
QUnit.test("countNew", assert => {
const store = createStore();
const foo = store.createRecord("category", {
id: 1,
slug: "foo"
});
const bar = store.createRecord("category", {
id: 2,
slug: "bar",
parent_category_id: foo.id
});
const baz = store.createRecord("category", {
id: 3,
slug: "baz",
parent_category_id: bar.id
});
const qux = store.createRecord("category", {
id: 4,
slug: "qux"
});
sandbox.stub(Category, "list").returns([foo, bar, baz, qux]);
let currentUser = User.create({
username: "chuck",
muted_category_ids: [4]
});
const state = TopicTrackingState.create({ currentUser });
assert.equal(state.countNew(1), 0);
assert.equal(state.countNew(2), 0);
assert.equal(state.countNew(3), 0);
state.states["t112"] = {
last_read_post_number: null,
id: 112,
notification_level: NotificationLevels.TRACKING,
category_id: 2
};
assert.equal(state.countNew(1), 1);
assert.equal(state.countNew(1, "missing-tag"), 0);
assert.equal(state.countNew(2), 1);
assert.equal(state.countNew(3), 0);
state.states["t113"] = {
last_read_post_number: null,
id: 113,
notification_level: NotificationLevels.TRACKING,
category_id: 3,
tags: ["amazing"]
};
assert.equal(state.countNew(1), 2);
assert.equal(state.countNew(2), 2);
assert.equal(state.countNew(3), 1);
assert.equal(state.countNew(3, "amazing"), 1);
assert.equal(state.countNew(3, "missing"), 0);
state.states["t111"] = {
last_read_post_number: null,
id: 111,
notification_level: NotificationLevels.TRACKING,
category_id: 1
};
assert.equal(state.countNew(1), 3);
assert.equal(state.countNew(2), 2);
assert.equal(state.countNew(3), 1);
state.states["t115"] = {
last_read_post_number: null,
id: 115,
category_id: 4
};
assert.equal(state.countNew(4), 0);
});
QUnit.test("mute topic", function(assert) {
let currentUser = User.create({
username: "chuck",
muted_category_ids: []
});
const state = TopicTrackingState.create({ currentUser });
state.trackMutedTopic(1);
assert.equal(currentUser.muted_topics[0].topicId, 1);
state.pruneOldMutedTopics();
assert.equal(state.isMutedTopic(1), true);
this.clock.tick(60000);
state.pruneOldMutedTopics();
assert.equal(state.isMutedTopic(1), false);
});