From bcb13f3a494cbe72814cf60c2521121b27c5e722 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Fri, 6 Mar 2026 16:34:53 +0200 Subject: [PATCH] tests --- src/modules/users.js | 2 +- src/stores/user_highlight.js | 12 +- test/unit/specs/stores/sync_config.spec.js | 2 +- test/unit/specs/stores/user_highlight.spec.js | 292 ++++++++++++++++++ 4 files changed, 301 insertions(+), 7 deletions(-) create mode 100644 test/unit/specs/stores/user_highlight.spec.js diff --git a/src/modules/users.js b/src/modules/users.js index ffc40ff25..db0c12442 100644 --- a/src/modules/users.js +++ b/src/modules/users.js @@ -703,7 +703,7 @@ const users = { commit('setCurrentUser', user) useSyncConfigStore().initSyncConfig(user) - useUserHighlightStore().initHighlight(user) + useUserHighlightStore().initUserHighlight(user) commit('addNewUsers', [user]) useEmojiStore().fetchEmoji() diff --git a/src/stores/user_highlight.js b/src/stores/user_highlight.js index e990cc36f..df9274bdf 100644 --- a/src/stores/user_highlight.js +++ b/src/stores/user_highlight.js @@ -169,16 +169,18 @@ export const _mergePrefs = (recent, stale) => { `journal contains entry to edit internal (starts with _) field '${user}', something is incorrect here, ignoring.`, ) } + console.log(resultOutput) switch (operation) { case 'set': - resultOutput[user] = args[0] + resultOutput.highlight[user] = args[0] break case 'unset': - delete resultOutput[user] + delete resultOutput.highlight[user] break default: return console.error(`Unknown journal operation: '${operation}'`) } + console.log(resultOutput) }) return { ...resultOutput, _journal: totalJournal } } @@ -260,7 +262,7 @@ export const useUserHighlightStore = defineStore('user_highlight', { this.raw.highlight._journal = [] this.pushSyncConfig() }, - initHighlight(userData) { + initUserHighlight(userData) { const live = userData.user_highlight this.raw = live let cache = this.cache @@ -319,12 +321,12 @@ export const useUserHighlightStore = defineStore('user_highlight', { if (!needPush) return this.updateCache({ username: window.vuex.state.users.currentUser.fqn }) const params = { - pleroma_settings_store: { 'user_highlight': this.cache }, + pleroma_settings_store: { user_highlight: this.cache }, } window.vuex.state.api.backendInteractor .updateProfileJSON({ params }) .then((user) => { - this.initHighlight(user) + this.initUserHighlight(user) this.dirty = false }) }, diff --git a/test/unit/specs/stores/sync_config.spec.js b/test/unit/specs/stores/sync_config.spec.js index 5ae4ab9cc..b065bede9 100644 --- a/test/unit/specs/stores/sync_config.spec.js +++ b/test/unit/specs/stores/sync_config.spec.js @@ -16,7 +16,7 @@ import { VERSION, } from 'src/stores/sync_config.js' -describe('The SyncConfig module', () => { +describe('The SyncConfig store', () => { beforeEach(() => { setActivePinia(createPinia()) }) diff --git a/test/unit/specs/stores/user_highlight.spec.js b/test/unit/specs/stores/user_highlight.spec.js new file mode 100644 index 000000000..d58626876 --- /dev/null +++ b/test/unit/specs/stores/user_highlight.spec.js @@ -0,0 +1,292 @@ +import { cloneDeep } from 'lodash' +import { createPinia, setActivePinia } from 'pinia' + +import { + _getRecentData, + _mergePrefs, + _moveItemInArray, + useUserHighlightStore, +} from 'src/stores/user_highlight.js' + +describe('The UserHighlight store', () => { + beforeEach(() => { + setActivePinia(createPinia()) + }) + + describe('mutations', () => { + describe('initUserHighlight', () => { + const user = { + created_at: new Date('1999-02-09'), + storage: {}, + } + + it('should initialize storage if none present', () => { + const store = useUserHighlightStore() + store.initUserHighlight({ ...user }) + expect(store.cache._timestamp).to.be.a('number') + expect(store.cache.highlight).to.eql({ _journal: [] }) + }) + + it('should initialize storage for new users if none present', () => { + const store = useUserHighlightStore() + store.initUserHighlight({ ...user, created_at: new Date() }) + expect(store.cache._timestamp).to.be.a('number') + expect(store.cache.highlight).to.eql({ _journal: [] }) + }) + + it('should use remote version if local missing', () => { + const store = useUserHighlightStore() + store.initUserHighlight(store, user) + expect(store.cache._timestamp).to.be.a('number') + }) + }) + describe('set', () => { + it('should set preference and update journal log accordingly', () => { + const store = useUserHighlightStore() + store.set({ user: 'highlight@testing', value: { type: 'test' }}) + expect(store.highlight['highlight@testing']).to.eql({ user: 'highlight@testing', type: 'test' }) + expect(store.highlight._journal.length).to.eql(1) + expect(store.highlight._journal[0]).to.eql({ + user: 'highlight@testing', + operation: 'set', + args: [{ user: 'highlight@testing', type: 'test' }], + // should have A timestamp, we don't really care what it is + timestamp: store.highlight._journal[0].timestamp, + }) + }) + + it('should keep journal to a minimum', () => { + const store = useUserHighlightStore() + store.set({ user: 'highlight@testing.xyz', value: { type: 'test' } }) + store.set({ user: 'highlight@testing.xyz', value: { type: 'test' } }) + store.updateCache({ username: 'test' }) + expect(store.highlight['highlight@testing.xyz']).to.eql({ user: 'highlight@testing.xyz', type: 'test' }) + expect(store.highlight._journal.length).to.eql(1) + expect(store.highlight._journal[0]).to.eql({ + user: 'highlight@testing.xyz', + operation: 'set', + args: [{ + user: 'highlight@testing.xyz', + type: 'test', + }], + // should have A timestamp, we don't really care what it is + timestamp: store.highlight._journal[0].timestamp, + }) + }) + + it('should remove duplicate entries from journal', () => { + const store = useUserHighlightStore() + store.set({ user: 'a@test.xyz', value: { type: 'foo' } }) + store.set({ user: 'a@test.xyz', value: { type: 'foo' } }) + store.updateCache({ username: 'test' }) + expect(store.highlight['a@test.xyz']).to.eql({ user: 'a@test.xyz', type: 'foo' }) + expect(store.highlight._journal.length).to.eql(1) + }) + }) + }) + + describe('helper functions', () => { + describe('_getRecentData', () => { + it('should handle nulls correctly', () => { + expect(_getRecentData(null, null, true)).to.eql({ + recent: null, + stale: null, + needUpload: true, + }) + }) + + it("doesn't choke on invalid data", () => { + expect(_getRecentData({ a: 1 }, { b: 2 }, true)).to.eql({ + recent: null, + stale: null, + needUpload: true, + }) + }) + + it('should prefer the valid non-null correctly, needUpload works properly', () => { + const nonNull = { _timestamp: 1 } + expect(_getRecentData(nonNull, null, true)).to.eql({ + recent: nonNull, + stale: null, + needUpload: true, + }) + expect(_getRecentData(null, nonNull, true)).to.eql({ + recent: nonNull, + stale: null, + needUpload: false, + }) + }) + + it('should prefer the one with higher timestamp', () => { + const a = { _timestamp: 1 } + const b = { _timestamp: 2 } + + expect(_getRecentData(a, b, true)).to.eql({ + recent: b, + stale: a, + needUpload: false, + }) + expect(_getRecentData(b, a, true)).to.eql({ + recent: b, + stale: a, + needUpload: false, + }) + }) + + it('case where both are same', () => { + const a = { _timestamp: 3 } + const b = { _timestamp: 3 } + + expect(_getRecentData(a, b, true)).to.eql({ + recent: b, + stale: a, + needUpload: false, + }) + expect(_getRecentData(b, a, true)).to.eql({ + recent: b, + stale: a, + needUpload: false, + }) + }) + }) + + describe('_mergePrefs', () => { + it('should prefer recent and apply journal to it', () => { + expect( + _mergePrefs( + // RECENT + { + highlight: { 'a@test.xyz': 1, 'b@test.xyz': 0, 'c@test.xyz': true }, + _journal: [ + { + user: 'b@test.xyz', + operation: 'set', + args: [0], + timestamp: 2, + }, + { + user: 'c@test.xyz', + operation: 'set', + args: [true], + timestamp: 4, + }, + ], + }, + // STALE + { + highlight: { 'a@test.xyz': 1, 'b@test.xyz': 1, 'c@test.xyz': false }, + _journal: [ + { + user: 'a@test.xyz', + operation: 'set', + args: [1], + timestamp: 1, + }, + { + user: 'b@test.xyz', + operation: 'set', + args: [1], + timestamp: 3, + }, + ], + }, + ), + ).to.eql({ + highlight: { 'a@test.xyz': 1, 'b@test.xyz': 1, 'c@test.xyz': true }, + _journal: [ + { user: 'a@test.xyz', operation: 'set', args: [1], timestamp: 1 }, + { user: 'b@test.xyz', operation: 'set', args: [1], timestamp: 3 }, + { + user: 'c@test.xyz', + operation: 'set', + args: [true], + timestamp: 4, + }, + ], + }) + }) + + it('should work with objects', () => { + expect( + _mergePrefs( + // RECENT + { + highlight: { 'a@test.xyz': { type: 'foo' } }, + _journal: [ + { + user: 'a@test.xyz', + operation: 'set', + args: [{ type: 'foo' }], + timestamp: 2, + }, + ], + }, + // STALE + { + highlight: { 'a@test.xyz': { type: 'bar' } }, + _journal: [ + { + user: 'a@test.xyz', + operation: 'set', + args: [{ type: 'bar' }], + timestamp: 4, + }, + ], + }, + ), + ).to.eql({ + highlight: { 'a@test.xyz': { type: 'bar' } }, + _journal: [ + { + user: 'a@test.xyz', + operation: 'set', + args: [{ type: 'bar' }], + timestamp: 4, + }, + ], + }) + }) + + it('should work with unset', () => { + expect( + _mergePrefs( + // RECENT + { + highlight: { 'a@test.xyz': { type: 'foo' } }, + _journal: [ + { + user: 'a@test.xyz', + operation: 'set', + args: [{ type: 'foo' }], + timestamp: 2, + }, + ], + }, + // STALE + { + highlight: {}, + _journal: [ + { + user: 'a@test.xyz', + operation: 'unset', + args: [], + timestamp: 4, + }, + ], + }, + ), + ).to.eql({ + highlight: {}, + _journal: [ + { + user: 'a@test.xyz', + operation: 'unset', + args: [], + timestamp: 4, + }, + ], + }) + }) + }) + }) +})