Clean up user data a tad
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
import {Scope, FeedController, FeedControllerOptions, Feed} from "@welshman/feeds"
|
import {Scope, FeedController, FeedControllerOptions, Feed} from "@welshman/feeds"
|
||||||
import {pubkey, signer} from "./session.js"
|
import {pubkey, signer} from "./session.js"
|
||||||
import {wotGraph, maxWot, getFollows, getNetwork, getFollowers} from "./wot.js"
|
import {getWotGraph, getMaxWot, getFollows, getNetwork, getFollowers} from "./wot.js"
|
||||||
|
|
||||||
export const getPubkeysForScope = (scope: string) => {
|
export const getPubkeysForScope = (scope: string) => {
|
||||||
const $pubkey = pubkey.get()
|
const $pubkey = pubkey.get()
|
||||||
@@ -25,10 +25,11 @@ export const getPubkeysForScope = (scope: string) => {
|
|||||||
|
|
||||||
export const getPubkeysForWOTRange = (min: number, max: number) => {
|
export const getPubkeysForWOTRange = (min: number, max: number) => {
|
||||||
const pubkeys = []
|
const pubkeys = []
|
||||||
const thresholdMin = maxWot.get() * min
|
const $maxWot = getMaxWot()
|
||||||
const thresholdMax = maxWot.get() * max
|
const thresholdMin = $maxWot * min
|
||||||
|
const thresholdMax = $maxWot * max
|
||||||
|
|
||||||
for (const [tpk, score] of wotGraph.get().entries()) {
|
for (const [tpk, score] of getWotGraph().entries()) {
|
||||||
if (score >= thresholdMin && score <= thresholdMax) {
|
if (score >= thresholdMin && score <= thresholdMax) {
|
||||||
pubkeys.push(tpk)
|
pubkeys.push(tpk)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import {PROFILE, PublishedProfile, RelayProfile} from "@welshman/util"
|
|||||||
import {load} from "@welshman/net"
|
import {load} from "@welshman/net"
|
||||||
import {throttled} from "@welshman/store"
|
import {throttled} from "@welshman/store"
|
||||||
import {Router} from "@welshman/router"
|
import {Router} from "@welshman/router"
|
||||||
import {wotGraph, maxWot} from "./wot.js"
|
import {getWotGraph, getMaxWot} from "./wot.js"
|
||||||
import {profiles} from "./profiles.js"
|
import {profiles} from "./profiles.js"
|
||||||
import {topics, Topic} from "./topics.js"
|
import {topics, Topic} from "./topics.js"
|
||||||
import {relays} from "./relays.js"
|
import {relays} from "./relays.js"
|
||||||
@@ -75,9 +75,9 @@ export const profileSearch = derived(
|
|||||||
onSearch: searchProfiles,
|
onSearch: searchProfiles,
|
||||||
getValue: (profile: PublishedProfile) => profile.event.pubkey,
|
getValue: (profile: PublishedProfile) => profile.event.pubkey,
|
||||||
sortFn: ({score = 1, item}) => {
|
sortFn: ({score = 1, item}) => {
|
||||||
const wotScore = wotGraph.get().get(item.event.pubkey) || 0
|
const wotScore = getWotGraph().get(item.event.pubkey) || 0
|
||||||
|
|
||||||
return dec(score) * inc(wotScore / maxWot.get())
|
return dec(score) * inc(wotScore / getMaxWot())
|
||||||
},
|
},
|
||||||
fuseOptions: {
|
fuseOptions: {
|
||||||
keys: [
|
keys: [
|
||||||
|
|||||||
+25
-58
@@ -1,5 +1,5 @@
|
|||||||
import {derived, Readable} from "svelte/store"
|
import {derived, Readable} from "svelte/store"
|
||||||
import {withGetter, memoized} from "@welshman/store"
|
import {ItemsByKey} from "@welshman/store"
|
||||||
import {pubkey} from "./session.js"
|
import {pubkey} from "./session.js"
|
||||||
import {profilesByPubkey, forceLoadProfile, loadProfile} from "./profiles.js"
|
import {profilesByPubkey, forceLoadProfile, loadProfile} from "./profiles.js"
|
||||||
import {followListsByPubkey, forceLoadFollowList, loadFollowList} from "./follows.js"
|
import {followListsByPubkey, forceLoadFollowList, loadFollowList} from "./follows.js"
|
||||||
@@ -16,94 +16,61 @@ import {
|
|||||||
forceLoadMessagingRelayList,
|
forceLoadMessagingRelayList,
|
||||||
loadMessagingRelayList,
|
loadMessagingRelayList,
|
||||||
} from "./messagingRelayLists.js"
|
} from "./messagingRelayLists.js"
|
||||||
import {wotGraph} from "./wot.js"
|
import {wotGraph, getWotGraph} from "./wot.js"
|
||||||
|
|
||||||
export type UserDataLoader = (pubkey: string, relays?: string[], force?: boolean) => unknown
|
export const makeUserData = <T>(
|
||||||
|
itemsByKey: Readable<ItemsByKey<T>>,
|
||||||
|
onDerive?: (key: string, ...args: any[]) => void,
|
||||||
|
) =>
|
||||||
|
derived([itemsByKey, pubkey], ([$itemsByKey, $pubkey]) => {
|
||||||
|
if (!$pubkey) return undefined
|
||||||
|
|
||||||
export type MakeUserDataOptions<T> = {
|
onDerive?.($pubkey)
|
||||||
mapStore: Readable<Map<string, T>>
|
|
||||||
loadItem: UserDataLoader
|
|
||||||
}
|
|
||||||
|
|
||||||
export const makeUserData = <T>({mapStore, loadItem}: MakeUserDataOptions<T>) =>
|
return $itemsByKey.get($pubkey)
|
||||||
withGetter(
|
})
|
||||||
memoized(
|
|
||||||
derived([mapStore, pubkey], ([$mapStore, $pubkey]) => {
|
|
||||||
if (!$pubkey) return undefined
|
|
||||||
|
|
||||||
loadItem($pubkey)
|
|
||||||
|
|
||||||
return $mapStore.get($pubkey)
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
export const makeUserLoader =
|
export const makeUserLoader =
|
||||||
(loadItem: UserDataLoader) =>
|
(loadItem: (key: string, ...args: any[]) => void) =>
|
||||||
async (relays: string[] = [], force = false) => {
|
async (...args: any[]) => {
|
||||||
const $pubkey = pubkey.get()
|
const $pubkey = pubkey.get()
|
||||||
|
|
||||||
if ($pubkey) {
|
if ($pubkey) {
|
||||||
await loadItem($pubkey, relays, force)
|
await loadItem($pubkey, ...args)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const userProfile = makeUserData({
|
export const userProfile = makeUserData(profilesByPubkey, loadProfile)
|
||||||
mapStore: profilesByPubkey,
|
|
||||||
loadItem: loadProfile,
|
|
||||||
})
|
|
||||||
|
|
||||||
export const forceLoadUserProfile = makeUserLoader(forceLoadProfile)
|
export const forceLoadUserProfile = makeUserLoader(forceLoadProfile)
|
||||||
export const loadUserProfile = makeUserLoader(loadProfile)
|
export const loadUserProfile = makeUserLoader(loadProfile)
|
||||||
|
|
||||||
export const userFollowList = makeUserData({
|
export const userFollowList = makeUserData(followListsByPubkey, loadFollowList)
|
||||||
mapStore: followListsByPubkey,
|
|
||||||
loadItem: loadFollowList,
|
|
||||||
})
|
|
||||||
|
|
||||||
export const forceLoadUserFollowList = makeUserLoader(forceLoadFollowList)
|
export const forceLoadUserFollowList = makeUserLoader(forceLoadFollowList)
|
||||||
export const loadUserFollowList = makeUserLoader(loadFollowList)
|
export const loadUserFollowList = makeUserLoader(loadFollowList)
|
||||||
|
|
||||||
export const userMuteList = makeUserData({
|
export const userMuteList = makeUserData(muteListsByPubkey, loadMuteList)
|
||||||
mapStore: muteListsByPubkey,
|
|
||||||
loadItem: loadMuteList,
|
|
||||||
})
|
|
||||||
|
|
||||||
export const forceLoadUserMuteList = makeUserLoader(forceLoadMuteList)
|
export const forceLoadUserMuteList = makeUserLoader(forceLoadMuteList)
|
||||||
export const loadUserMuteList = makeUserLoader(loadMuteList)
|
export const loadUserMuteList = makeUserLoader(loadMuteList)
|
||||||
|
|
||||||
export const userPinList = makeUserData({
|
export const userPinList = makeUserData(pinListsByPubkey, loadPinList)
|
||||||
mapStore: pinListsByPubkey,
|
|
||||||
loadItem: loadPinList,
|
|
||||||
})
|
|
||||||
|
|
||||||
export const forceLoadUserPinList = makeUserLoader(forceLoadPinList)
|
export const forceLoadUserPinList = makeUserLoader(forceLoadPinList)
|
||||||
export const loadUserPinList = makeUserLoader(loadPinList)
|
export const loadUserPinList = makeUserLoader(loadPinList)
|
||||||
|
|
||||||
export const userRelayList = makeUserData({
|
export const userRelayList = makeUserData(relayListsByPubkey, loadRelayList)
|
||||||
mapStore: relayListsByPubkey,
|
|
||||||
loadItem: loadRelayList,
|
|
||||||
})
|
|
||||||
|
|
||||||
export const forceLoadUserRelayList = makeUserLoader(forceLoadRelayList)
|
export const forceLoadUserRelayList = makeUserLoader(forceLoadRelayList)
|
||||||
export const loadUserRelayList = makeUserLoader(loadRelayList)
|
export const loadUserRelayList = makeUserLoader(loadRelayList)
|
||||||
|
|
||||||
export const userMessagingRelayList = makeUserData({
|
export const userMessagingRelayList = makeUserData(
|
||||||
mapStore: messagingRelayListsByPubkey,
|
messagingRelayListsByPubkey,
|
||||||
loadItem: loadMessagingRelayList,
|
loadMessagingRelayList,
|
||||||
})
|
)
|
||||||
|
|
||||||
export const forceLoadUserMessagingRelayList = makeUserLoader(forceLoadMessagingRelayList)
|
export const forceLoadUserMessagingRelayList = makeUserLoader(forceLoadMessagingRelayList)
|
||||||
export const loadUserMessagingRelayList = makeUserLoader(loadMessagingRelayList)
|
export const loadUserMessagingRelayList = makeUserLoader(loadMessagingRelayList)
|
||||||
|
|
||||||
export const userBlossomServerList = makeUserData({
|
export const userBlossomServerList = makeUserData(blossomServerListsByPubkey, loadBlossomServerList)
|
||||||
mapStore: blossomServerListsByPubkey,
|
|
||||||
loadItem: loadBlossomServerList,
|
|
||||||
})
|
|
||||||
|
|
||||||
export const forceLoadUserBlossomServerList = makeUserLoader(forceLoadBlossomServerList)
|
export const forceLoadUserBlossomServerList = makeUserLoader(forceLoadBlossomServerList)
|
||||||
export const loadUserBlossomServerList = makeUserLoader(loadBlossomServerList)
|
export const loadUserBlossomServerList = makeUserLoader(loadBlossomServerList)
|
||||||
|
|
||||||
export const getUserWotScore = (tpk: string) => wotGraph.get().get(tpk) || 0
|
export const getUserWotScore = (tpk: string) => getWotGraph().get(tpk) || 0
|
||||||
|
|
||||||
export const deriveUserWotScore = (tpk: string) => derived(wotGraph, $g => $g.get(tpk) || 0)
|
export const deriveUserWotScore = (tpk: string) => derived(wotGraph, $g => $g.get(tpk) || 0)
|
||||||
|
|||||||
+29
-26
@@ -1,7 +1,7 @@
|
|||||||
import {derived, writable} from "svelte/store"
|
import {derived, writable} from "svelte/store"
|
||||||
import {max, throttle, addToMapKey, inc, dec} from "@welshman/lib"
|
import {max, throttle, addToMapKey, inc, dec} from "@welshman/lib"
|
||||||
import {getListTags, getPubkeyTagValues} from "@welshman/util"
|
import {getListTags, getPubkeyTagValues} from "@welshman/util"
|
||||||
import {throttled, withGetter} from "@welshman/store"
|
import {throttled, getter} from "@welshman/store"
|
||||||
import {pubkey} from "./session.js"
|
import {pubkey} from "./session.js"
|
||||||
import {followLists, getFollowListsByPubkey, getFollowList} from "./follows.js"
|
import {followLists, getFollowListsByPubkey, getFollowList} from "./follows.js"
|
||||||
import {muteLists, getMuteList} from "./mutes.js"
|
import {muteLists, getMuteList} from "./mutes.js"
|
||||||
@@ -25,38 +25,37 @@ export const getNetwork = (pubkey: string) => {
|
|||||||
return Array.from(network)
|
return Array.from(network)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const followersByPubkey = withGetter(
|
export const followersByPubkey = derived(throttled(1000, followLists), lists => {
|
||||||
derived(throttled(1000, followLists), lists => {
|
const $followersByPubkey = new Map<string, Set<string>>()
|
||||||
const $followersByPubkey = new Map<string, Set<string>>()
|
|
||||||
|
|
||||||
for (const list of lists) {
|
for (const list of lists) {
|
||||||
for (const pubkey of getPubkeyTagValues(getListTags(list))) {
|
for (const pubkey of getPubkeyTagValues(getListTags(list))) {
|
||||||
addToMapKey($followersByPubkey, pubkey, list.event.pubkey)
|
addToMapKey($followersByPubkey, pubkey, list.event.pubkey)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return $followersByPubkey
|
return $followersByPubkey
|
||||||
}),
|
})
|
||||||
)
|
|
||||||
|
|
||||||
export const mutersByPubkey = withGetter(
|
export const getFollowersByPubkey = getter(followersByPubkey)
|
||||||
derived(throttled(1000, muteLists), lists => {
|
|
||||||
const $mutersByPubkey = new Map<string, Set<string>>()
|
|
||||||
|
|
||||||
for (const list of lists) {
|
export const mutersByPubkey = derived(throttled(1000, muteLists), lists => {
|
||||||
for (const pubkey of getPubkeyTagValues(getListTags(list))) {
|
const $mutersByPubkey = new Map<string, Set<string>>()
|
||||||
addToMapKey($mutersByPubkey, pubkey, list.event.pubkey)
|
|
||||||
}
|
for (const list of lists) {
|
||||||
|
for (const pubkey of getPubkeyTagValues(getListTags(list))) {
|
||||||
|
addToMapKey($mutersByPubkey, pubkey, list.event.pubkey)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return $mutersByPubkey
|
return $mutersByPubkey
|
||||||
}),
|
})
|
||||||
)
|
|
||||||
|
|
||||||
export const getFollowers = (pubkey: string) =>
|
export const getMutersByPubkey = getter(mutersByPubkey)
|
||||||
Array.from(followersByPubkey.get().get(pubkey) || [])
|
|
||||||
|
|
||||||
export const getMuters = (pubkey: string) => Array.from(mutersByPubkey.get().get(pubkey) || [])
|
export const getFollowers = (pubkey: string) => Array.from(getFollowersByPubkey().get(pubkey) || [])
|
||||||
|
|
||||||
|
export const getMuters = (pubkey: string) => Array.from(getMutersByPubkey().get(pubkey) || [])
|
||||||
|
|
||||||
export const getFollowsWhoFollow = (pubkey: string, target: string) =>
|
export const getFollowsWhoFollow = (pubkey: string, target: string) =>
|
||||||
getFollows(pubkey).filter(other => getFollows(other).includes(target))
|
getFollows(pubkey).filter(other => getFollows(other).includes(target))
|
||||||
@@ -64,9 +63,13 @@ export const getFollowsWhoFollow = (pubkey: string, target: string) =>
|
|||||||
export const getFollowsWhoMute = (pubkey: string, target: string) =>
|
export const getFollowsWhoMute = (pubkey: string, target: string) =>
|
||||||
getFollows(pubkey).filter(other => getMutes(other).includes(target))
|
getFollows(pubkey).filter(other => getMutes(other).includes(target))
|
||||||
|
|
||||||
export const wotGraph = withGetter(writable(new Map<string, number>()))
|
export const wotGraph = writable(new Map<string, number>())
|
||||||
|
|
||||||
export const maxWot = withGetter(derived(wotGraph, $g => max(Array.from($g.values()))))
|
export const getWotGraph = getter(wotGraph)
|
||||||
|
|
||||||
|
export const maxWot = derived(wotGraph, $g => max(Array.from($g.values())))
|
||||||
|
|
||||||
|
export const getMaxWot = getter(maxWot)
|
||||||
|
|
||||||
const buildGraph = throttle(1000, () => {
|
const buildGraph = throttle(1000, () => {
|
||||||
const $pubkey = pubkey.get()
|
const $pubkey = pubkey.get()
|
||||||
|
|||||||
@@ -110,7 +110,6 @@ export class Repository extends Emitter {
|
|||||||
removed.add(id)
|
removed.add(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("UPDATE")
|
|
||||||
this.emit("update", {added, removed})
|
this.emit("update", {added, removed})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,6 @@
|
|||||||
import {TrustedEvent} from "@welshman/util"
|
|
||||||
import {Repository} from "@welshman/net"
|
|
||||||
import {get} from "svelte/store"
|
import {get} from "svelte/store"
|
||||||
import {afterEach, beforeEach, describe, expect, it, vi} from "vitest"
|
import {afterEach, beforeEach, describe, expect, it, vi} from "vitest"
|
||||||
import {
|
import {getter, synced, localStorageProvider, throttled, withGetter} from "../src/index"
|
||||||
deriveEvents,
|
|
||||||
deriveIsDeleted,
|
|
||||||
getter,
|
|
||||||
synced,
|
|
||||||
localStorageProvider,
|
|
||||||
throttled,
|
|
||||||
withGetter,
|
|
||||||
} from "../src/index"
|
|
||||||
|
|
||||||
// Mock localStorage
|
// Mock localStorage
|
||||||
const localStorageMock = (() => {
|
const localStorageMock = (() => {
|
||||||
@@ -139,138 +129,4 @@ describe("Store utilities", () => {
|
|||||||
expect(mockFn).toHaveBeenLastCalledWith(3)
|
expect(mockFn).toHaveBeenLastCalledWith(3)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("custom", () => {
|
|
||||||
it("should handle updates correctly", () => {
|
|
||||||
const mockFn = vi.fn()
|
|
||||||
const store = custom<number>(set => {
|
|
||||||
set(0)
|
|
||||||
return () => {}
|
|
||||||
})
|
|
||||||
|
|
||||||
store.subscribe(mockFn)
|
|
||||||
store.set(1)
|
|
||||||
store.update(n => n + 1)
|
|
||||||
|
|
||||||
expect(mockFn).toHaveBeenCalledTimes(3) // Initial + set + update
|
|
||||||
expect(store.get()).toBe(2)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("Event-related stores", () => {
|
|
||||||
const mockRepository = {
|
|
||||||
query: vi.fn(),
|
|
||||||
isDeleted: vi.fn(),
|
|
||||||
isDeletedByAddress: vi.fn(),
|
|
||||||
on: vi.fn(),
|
|
||||||
off: vi.fn(),
|
|
||||||
} satisfies Partial<Repository>
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
vi.clearAllMocks()
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("deriveEvents", () => {
|
|
||||||
it("should derive events from repository", () => {
|
|
||||||
const mockEvent = {id: "1", content: "test"} as TrustedEvent
|
|
||||||
mockRepository.query.mockReturnValue([mockEvent])
|
|
||||||
|
|
||||||
const store = deriveEvents(mockRepository as any, {
|
|
||||||
filters: [],
|
|
||||||
})
|
|
||||||
|
|
||||||
const mockFn = vi.fn()
|
|
||||||
store.subscribe(mockFn)
|
|
||||||
|
|
||||||
expect(mockRepository.query).toHaveBeenCalled()
|
|
||||||
expect(mockFn).toHaveBeenCalledWith([mockEvent])
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("deriveEventsMapped", () => {
|
|
||||||
it("should map events to items", async () => {
|
|
||||||
const mockEvent = {id: "1", content: "test"} as TrustedEvent
|
|
||||||
mockRepository.query.mockReturnValue([mockEvent])
|
|
||||||
|
|
||||||
const store = deriveEventsMapped(mockRepository as any, {
|
|
||||||
filters: [],
|
|
||||||
eventToItem: event => ({id: event.id, mapped: true}),
|
|
||||||
itemToEvent: item => ({id: item.id, content: ""}) as TrustedEvent,
|
|
||||||
})
|
|
||||||
|
|
||||||
const mockFn = vi.fn()
|
|
||||||
store.subscribe(mockFn)
|
|
||||||
|
|
||||||
expect(mockRepository.query).toHaveBeenCalled()
|
|
||||||
expect(mockFn).toHaveBeenCalledWith([{id: "1", mapped: true}])
|
|
||||||
})
|
|
||||||
|
|
||||||
it("should handle async eventToItem mapping", async () => {
|
|
||||||
const mockEvent = {id: "1", content: "test"} as TrustedEvent
|
|
||||||
mockRepository.query.mockReturnValue([mockEvent])
|
|
||||||
|
|
||||||
const store = deriveEventsMapped(mockRepository as any, {
|
|
||||||
filters: [],
|
|
||||||
eventToItem: async event => ({id: event.id, mapped: true}),
|
|
||||||
itemToEvent: item => ({id: item.id, content: ""}) as TrustedEvent,
|
|
||||||
})
|
|
||||||
|
|
||||||
const mockFn = vi.fn()
|
|
||||||
store.subscribe(mockFn)
|
|
||||||
|
|
||||||
// Wait for async operations to complete
|
|
||||||
await vi.runAllTimersAsync()
|
|
||||||
|
|
||||||
expect(mockRepository.query).toHaveBeenCalled()
|
|
||||||
expect(mockFn).toHaveBeenCalledWith([{id: "1", mapped: true}])
|
|
||||||
})
|
|
||||||
|
|
||||||
it("should handle repository updates", () => {
|
|
||||||
const mockEvent = {id: "1", content: "test"} as TrustedEvent
|
|
||||||
mockRepository.query.mockReturnValue([mockEvent])
|
|
||||||
|
|
||||||
const store = deriveEventsMapped(mockRepository as any, {
|
|
||||||
filters: [{}],
|
|
||||||
eventToItem: event => ({id: event.id, mapped: true}),
|
|
||||||
itemToEvent: item => ({id: item.id, content: ""}) as TrustedEvent,
|
|
||||||
})
|
|
||||||
|
|
||||||
const mockFn = vi.fn()
|
|
||||||
store.subscribe(mockFn)
|
|
||||||
|
|
||||||
const [[_, callback]] = mockRepository.on.mock.calls
|
|
||||||
|
|
||||||
callback({
|
|
||||||
added: [{id: "2"} as TrustedEvent],
|
|
||||||
removed: new Set([mockEvent.id]),
|
|
||||||
})
|
|
||||||
|
|
||||||
vi.advanceTimersByTime(300) // Wait for batch delay
|
|
||||||
|
|
||||||
expect(mockFn).toHaveBeenLastCalledWith([{id: "2", mapped: true}])
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("deriveIsDeleted", () => {
|
|
||||||
it("should track deletion status", () => {
|
|
||||||
const mockEvent = {id: "1"} as TrustedEvent
|
|
||||||
|
|
||||||
mockRepository.isDeleted.mockReturnValue(false)
|
|
||||||
|
|
||||||
const store = deriveIsDeleted(mockRepository as any, mockEvent)
|
|
||||||
const mockFn = vi.fn()
|
|
||||||
store.subscribe(mockFn)
|
|
||||||
|
|
||||||
expect(mockRepository.isDeleted).toHaveBeenCalledWith(mockEvent)
|
|
||||||
expect(mockFn).toHaveBeenCalledWith(false)
|
|
||||||
|
|
||||||
const [[_, callback]] = mockRepository.on.mock.calls
|
|
||||||
|
|
||||||
callback()
|
|
||||||
|
|
||||||
expect(mockRepository.isDeleted).toHaveBeenCalledWith(mockEvent)
|
|
||||||
expect(mockFn).toHaveBeenCalledWith(false)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user