Something went wrong. Try again.
Mirror of https://github.com/improsocial/improAn extensible Bluesky client for web
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206import { describe, it } from "node:test";import assert from "node:assert/strict";import { DataLayer } from "/js/dataLayer/dataLayer.js";import { DraftMediaStore } from "/js/drafts.js";import { PreferencesProvider } from "/js/dataLayer/preferencesProvider.js";
function createMockApi(options = {}) { return { getProfile: async (did) => options.profiles?.[did] ?? null, isAuthenticated: options.isAuthenticated ?? false, getPreferences: async () => options.preferences ?? [], getLabelers: async () => options.labelers ?? [], updatePreferences: async () => {}, };}
function createDataLayer(api) { return new DataLayer( api, null, new PreferencesProvider(api), { resolveHandle: async () => null }, new DraftMediaStore("test-media"), );}
describe("constructor", () => { it("should initialize all components", () => { const mockApi = createMockApi(); const dataLayer = createDataLayer(mockApi);
assert(dataLayer.api !== undefined); assert(dataLayer.dataStore !== undefined); assert(dataLayer.patchStore !== undefined); assert(dataLayer.preferencesProvider !== undefined); assert(dataLayer.requests !== undefined); assert(dataLayer.mutations !== undefined); assert(dataLayer.derived !== undefined); assert(dataLayer.declarative !== undefined); });
it("should set isAuthenticated from api", () => { const mockApi = createMockApi({ isAuthenticated: true }); const dataLayer = createDataLayer(mockApi);
assert.deepEqual(dataLayer.isAuthenticated, true); });
it("should initialize empty subscribers array", () => { const mockApi = createMockApi(); const dataLayer = createDataLayer(mockApi);
assert.deepEqual(dataLayer.subscribers, []); });});
describe("initializePreferences", () => { it("should call preferencesProvider.fetchPreferences", async () => { const mockApi = createMockApi({ isAuthenticated: false }); const dataLayer = createDataLayer(mockApi);
await dataLayer.initializePreferences();
// Verify preferences were loaded (logged out preferences for unauthenticated) const preferences = dataLayer.preferencesProvider.requirePreferences(); assert(preferences !== null); });
it("should fetch preferences from API when authenticated", async () => { const mockPreferences = [ { $type: "app.bsky.actor.defs#savedFeedsPrefV2", items: [] }, ]; const mockApi = createMockApi({ isAuthenticated: true, preferences: mockPreferences, }); const dataLayer = createDataLayer(mockApi);
await dataLayer.initializePreferences();
const preferences = dataLayer.preferencesProvider.requirePreferences(); assert.deepEqual(preferences.obj, mockPreferences); });});
describe("hasCachedFeed", () => { it("should return false when feed not cached", () => { const mockApi = createMockApi(); const dataLayer = createDataLayer(mockApi);
const result = dataLayer.hasCachedFeed("at://feed/uri");
assert.deepEqual(result, false); });
it("should return true when feed is cached", () => { const mockApi = createMockApi(); const dataLayer = createDataLayer(mockApi); const feedURI = "at://feed/uri";
dataLayer.dataStore.$feeds.set(feedURI, { feed: [], cursor: null });
const result = dataLayer.hasCachedFeed(feedURI);
assert.deepEqual(result, true); });});
describe("hasCachedAuthorFeed", () => { it("should return false when author feed not cached", () => { const mockApi = createMockApi(); const dataLayer = createDataLayer(mockApi);
const result = dataLayer.hasCachedAuthorFeed("did:test:user", "posts");
assert.deepEqual(result, false); });
it("should return true when author feed is cached", () => { const mockApi = createMockApi(); const dataLayer = createDataLayer(mockApi); const profileDid = "did:test:user"; const feedType = "posts";
dataLayer.dataStore.$authorFeeds.set(`${profileDid}-${feedType}`, { feed: [], cursor: null, });
const result = dataLayer.hasCachedAuthorFeed(profileDid, feedType);
assert.deepEqual(result, true); });
it("should construct correct feed URI from profileDid and feedType", () => { const mockApi = createMockApi(); const dataLayer = createDataLayer(mockApi); const profileDid = "did:test:user"; const feedType = "replies";
// Cache with the expected URI format dataLayer.dataStore.$authorFeeds.set("did:test:user-replies", { feed: [], cursor: null, });
const result = dataLayer.hasCachedAuthorFeed(profileDid, feedType);
assert.deepEqual(result, true); });});
describe("component integration", () => { it("should pass dataStore to derived", async () => { const mockApi = createMockApi({ isAuthenticated: false }); const dataLayer = createDataLayer(mockApi); const postURI = "at://post/uri"; const post = { uri: postURI, text: "test", likeCount: 5 };
// Initialize preferences first (required by derived) await dataLayer.initializePreferences();
// Set data through dataStore dataLayer.dataStore.$posts.set(postURI, post);
// Verify derived can access it const result = dataLayer.derived.$hydratedPosts.get(postURI); assert.deepEqual(result.uri, postURI); });
it("should pass patchStore to derived", async () => { const mockApi = createMockApi({ isAuthenticated: false }); const dataLayer = createDataLayer(mockApi); const postURI = "at://post/uri"; const post = { uri: postURI, likeCount: 5, viewer: { like: null } };
// Initialize preferences first (required by derived) await dataLayer.initializePreferences();
dataLayer.dataStore.$posts.set(postURI, post); dataLayer.patchStore.addPostPatch(postURI, { type: "addLike" });
// Verify derived apply patches const result = dataLayer.derived.$hydratedPosts.get(postURI); assert.deepEqual(result.likeCount, 6); });
it("should pass derived and requests to declarative", async () => { const mockApi = createMockApi({ isAuthenticated: false, profiles: { "did:test:user": { did: "did:test:user", handle: "test.user" }, }, }); const dataLayer = createDataLayer(mockApi);
// Initialize preferences first await dataLayer.initializePreferences();
// Verify declarative can access derived const profile = await dataLayer.declarative.ensureDetailedProfile("did:test:user"); assert(profile !== null); });});