From 7e54f806a940752481e7924c2dc6e5a19ac2401a Mon Sep 17 00:00:00 2001 From: balzack Date: Sun, 7 Jul 2024 21:44:38 -0700 Subject: [PATCH] extending session test --- app/sdk/__mocks__/account.ts | 64 ++++++++++ app/sdk/__mocks__/alias.ts | 50 ++++++++ app/sdk/__mocks__/attribute.ts | 58 +++++++++ app/sdk/__mocks__/contact.ts | 192 +++++++++++++++++++++++++++++ app/sdk/__mocks__/content.ts | 131 ++++++++++++++++++++ app/sdk/__mocks__/identity.ts | 43 +++++++ app/sdk/__mocks__/waitFor.ts | 10 ++ app/sdk/__tests__/session.tests.ts | 77 +++++++++++- 8 files changed, 620 insertions(+), 5 deletions(-) create mode 100644 app/sdk/__mocks__/account.ts create mode 100644 app/sdk/__mocks__/alias.ts create mode 100644 app/sdk/__mocks__/attribute.ts create mode 100644 app/sdk/__mocks__/contact.ts create mode 100644 app/sdk/__mocks__/content.ts create mode 100644 app/sdk/__mocks__/identity.ts create mode 100644 app/sdk/__mocks__/waitFor.ts diff --git a/app/sdk/__mocks__/account.ts b/app/sdk/__mocks__/account.ts new file mode 100644 index 00000000..99e45ef2 --- /dev/null +++ b/app/sdk/__mocks__/account.ts @@ -0,0 +1,64 @@ +import { EventEmitter } from 'eventemitter3'; +import { type Account } from '../src/api'; +import type { AccountStatus } from '../src/types'; + +export class MockAccountModule implements Account { + + public revision: number; + private emitter: EventEmitter; + + constructor() { + this.revision = 0; + this.emitter = new EventEmitter(); + } + + public addStatusListener(ev: (status: AccountStatus) => void): void { + this.emitter.on('status', ev); + } + + public removeStatusListener(ev: (status: AccountStatus) => void): void { + this.emitter.off('status', ev); + } + + public close(): void { + } + + public async setRevision(rev: number): Promise { + this.revision = rev; + } + + public async enableNotifications(): Promise { + } + + public async disableNotifications(): Promise { + } + + public async enableRegistry(): Promise { + } + + public async disableRegistry(): Promise { + } + + public async enableMFA(): Promise<{ secretImage: string, secretText: string }> { + return { secretImage: '', secretText: '' }; + } + + public async disableMFA(): Promise { + } + + public async confirmMFA(code: string): Promise { + } + + public async setAccountSeal(password: string): Promise { + } + + public async clearAccountSeal(): Promise { + } + + public async unlockAccountSeal(password: string): Promise { + } + + public async setLogin(username: string, password: string): Promise { + } +} + diff --git a/app/sdk/__mocks__/alias.ts b/app/sdk/__mocks__/alias.ts new file mode 100644 index 00000000..7d0cb5be --- /dev/null +++ b/app/sdk/__mocks__/alias.ts @@ -0,0 +1,50 @@ +import { EventEmitter } from 'eventemitter3'; +import type { Alias, Account } from '../src/api'; +import type { Group } from '../src/types'; + +export class MockAliasModule implements Alias { + + public revision: number; + private emitter: EventEmitter; + + constructor() { + this.revision = 0; + this.emitter = new EventEmitter(); + } + + public addGroupListener(ev: (groups: Group[]) => void): void { + this.emitter.on('group', ev); + } + + public removeGroupListener(ev: (groups: Group[]) => void): void { + this.emitter.off('group', ev); + } + + public close(): void { + } + + public async setRevision(rev: number): Promise { + this.revision = rev; + } + + public async addGroup(sealed: boolean, dataType: string, subject: string, cardIds: string[]): Promise { + return ''; + } + + public async removeGroup(groupId: string): Promise { + } + + public async setGroupSubject(groupId: string, subject: string): Promise { + } + + public async setGroupCard(groupId: string, cardId: string): Promise { + } + + public async clearGroupCard(groupId: string, cardId: string): Promise { + } + + public async compare(groupIds: string[], cardIds: string[]): Promise> { + return new Map(); + } +} + diff --git a/app/sdk/__mocks__/attribute.ts b/app/sdk/__mocks__/attribute.ts new file mode 100644 index 00000000..66a78dfd --- /dev/null +++ b/app/sdk/__mocks__/attribute.ts @@ -0,0 +1,58 @@ +import { EventEmitter } from 'eventemitter3'; +import type { Attribute, Account } from '../src/api'; +import type { Article } from '../src/types'; + +export class MockAttributeModule implements Attribute { + + public revision: number; + private emitter: EventEmitter; + + constructor() { + this.revision = 0; + this.emitter = new EventEmitter(); + } + + public addCardListener(ev: (articles: Article[]) => void): void { + this.emitter.on('artcile', ev); + } + + public removeCardListener(ev: (articles: Article[]) => void): void { + this.emitter.off('article', ev); + } + + public close(): void { + } + + public async setRevision(rev: number): Promise { + this.revision = rev; + } + + public async addArticle(sealed: boolean, type: string, subject: string, cardIds: string[], groupIds: string[]): Promise { + return ''; + } + + public async removeArticle(articleId: string): Promise { + } + + public async setArticleSubject(articleId: string, subject: string): Promise { + } + + public async setArticleCard(articleId: string, cardId: string): Promise { + } + + public async clearArticleCard(articleId: string, cardId: string): Promise { + } + + public async setArticleGroup(articleId: string, groupId: string): Promise { + } + + public async clearArticleGroup(articleId: string, groupId: string): Promise { + } + + public addArticleListener(ev: (articles: Article[]) => void): void { + } + + public removeArticleListener(ev: (articles: Article[]) => void): void { + } +} + diff --git a/app/sdk/__mocks__/contact.ts b/app/sdk/__mocks__/contact.ts new file mode 100644 index 00000000..f6c94064 --- /dev/null +++ b/app/sdk/__mocks__/contact.ts @@ -0,0 +1,192 @@ +import { EventEmitter } from 'eventemitter3'; +import type { Contact } from '../src/api'; +import type { Card, Topic, Asset, Tag, Profile, Repeater} from '../src/types'; + +export class MockContactModule implements Contact { + + public revision: number; + private emitter: EventEmitter; + + constructor() { + this.revision = 0; + this.emitter = new EventEmitter(); + } + + public addCardListener(ev: (cards: Card[]) => void): void { + this.emitter.on('card', ev); + } + + public removeCardListener(ev: (cards: Card[]) => void): void { + this.emitter.off('card', ev); + } + + public close(): void { + } + + public async setRevision(rev: number): Promise { + this.revision = rev; + } + + public async addCard(server: string, guid: string): Promise { + return ''; + } + + public async removeCard(cardId: string): Promise { + } + + public async confirmCard(cardId: string): Promise { + } + + public async connectCard(cardId: string): Promise { + } + + public async disconnectCard(cardId: string): Promise { + } + + public async rejectCard(cardId: string): Promise { + } + + public async ignoreCard(cardId: string): Promise { + } + + public async resyncCard(cardId: string): Promise { + } + + public async flagCard(cardId: string): Promise { + } + + public async flagArticle(cardId: string, articleId: string): Promise { + } + + public async flagChannel(cardId: string, channelId: string): Promise { + } + + public async flagTopic(cardId: string, channelId: string, topicId: string): Promise { + } + + public async flagTag(cardId: string, channelId: string, topicId: string, tagId: string): Promise { + } + + public async setBlockCard(cardId: string): Promise { + } + + public async setBlockArticle(cardId: string, articleId: string): Promise { + } + + public async setBlockChannel(cardId: string, channelId: string): Promise { + } + + public async setBlockTopic(cardId: string, channelId: string, topicId: string): Promise { + } + + public async setBlockTag(cardId: string, channelId: string, topicId: string, tagId: string): Promise { + } + + public async clearBlockCard(cardId: string): Promise { + } + + public async clearBlockArticle(cardId: string, articleId: string): Promise { + } + + public async clearBlockChannel(cardId: string, channelId: string): Promise { + } + + public async clearBlockTopic(cardId: string, channelId: string, topicId: string): Promise { + } + + public async clearBlockTag(cardId: string, channelId: string, topicId: string, tagId: string): Promise { + } + + public async getBlockedCards(): Promise<{ cardId: string }[]> { + return []; + } + + public async getBlockedChannels(): Promise<{ cardId: string, channelId: string }[]> { + return []; + } + + public async getBlockedTopics(): Promise<{ cardId: string, channelId: string, topicId: string }[]> { + return []; + } + + public async getBlockedTags(): Promise<{ cardId: string, channelId: string, topicId: string, tagId: string }[]> { + return []; + } + + public async getBlockedArticles(): Promise<{ cardId: string, articleId: string }[]> { + return []; + } + + public async removeArticle(cardId: string, articleId: string): Promise { + } + + public async removeChannel(cardId: string, channelId: string): Promise { + } + + public async addTopic(cardId: string, channelId: string, type: string, message: string, assets: Asset[]): Promise { + return ''; + } + + public async removeTopic(cardId: string, channelId: string, topicId: string): Promise { + } + + public async setTopicSubject(cardId: string, channelId: string, topicId: string, subject: string): Promise { + } + + public async addTag(cardId: string, channelId: string, topicId: string, type: string, value: string): Promise { + return ''; + } + + public async removeTag(cardId: string, topicId: string, tagId: string): Promise { + } + + public async setTagSubject(cardId: string, topicId: string, tagId: string, subject: string): Promise { + } + + public async getTopics(cardId: string, channelId: string): Promise { + return []; + } + + public async getMoreTopics(cardId: string, channelId: string): Promise { + return []; + } + + public async getTags(cardId: string, channelId: string, topicId: string): Promise { + return []; + } + + public async getMoreTags(cardId: string, channelId: string, topicId: string): Promise { + return []; + } + + public async setUnreadChannel(cardId: string, channelId: string): Promise { + } + + public async clearUnreadChannel(cardId: string, channelId: string): Promise { + } + + public async getRegistry(server: string): Promise { + return []; + } + + public getRegistryImageUrl(server: string, guid: string): string { + return ''; + } + + public getTopicAssetUrl(cardId: string, channelId: string, topicId: string, assetId: string): string { + return ''; + } + + public getCardImageUrl(cardId: string): string { + return ''; + } + + public async addRepeaterAccess(cardId: string, channelId: string, name: string): Promise { + return { id: '', guid: '', name: '', server: '', token: '' }; + } + + public async removeRepeaterAccess(cardId: string, channelId: string, repeaterId: string): Promise { + } + +} + diff --git a/app/sdk/__mocks__/content.ts b/app/sdk/__mocks__/content.ts new file mode 100644 index 00000000..38278d91 --- /dev/null +++ b/app/sdk/__mocks__/content.ts @@ -0,0 +1,131 @@ +import { EventEmitter } from 'eventemitter3'; +import type { Content, Account } from '../src/api'; +import type { Channel, Topic, Asset, Tag, Repeater } from '../src/types'; + +export class MockContentModule implements Content { + + public revision: number; + private emitter: EventEmitter; + + constructor() { + this.revision = 0; + this.emitter = new EventEmitter(); + } + + public addChannelListener(ev: (channels: Channel[]) => void): void { + this.emitter.on('channel', ev); + } + + public removeChannelListener(ev: (channels: Channel[]) => void): void { + this.emitter.off('channel', ev); + } + + public close(): void { + } + + public async setRevision(rev: number): Promise { + this.revision = rev; + } + + public async addChannel(sealed: boolean, type: string, subject: string, cardIds: string[], groupIds: string[]): Promise { + return ''; + } + + public async removeChannel(channelId: string): Promise { + } + + public async setChannelSubject(channelId: string, subject: string): Promise { + } + + public async setChannelCard(channelId: string, cardId: string): Promise { + } + + public async clearChannelCard(channelId: string, cardId: string): Promise { + } + + public async setChannelGroup(channelId: string, groupId: string): Promise { + } + + public async clearChannelGroup(channelId: string, groupId: string): Promise { + } + + public async addTopic(channelId: string, type: string, subject: string, assets: Asset[]): Promise { + return ''; + } + + public async removeTopic(channelId: string, topicId: string): Promise { + } + + public async flagTopic(channelId: string, topicId: string): Promise { + } + + public async setTopicSubject(channelId: string, topicId: string, subject: string): Promise { + } + + public async addTag(channelId: string, topicId: string, type: string, value: string): Promise { + return ''; + } + + public async removeTag(channelId: string, topicId: string, tagId: string): Promise { + } + + public async setTagSubject(channelId: string, topicId: string, tagId: string, subject: string): Promise { + } + + public async flagTag(channelId: string, topicId: string, tagId: string): Promise { + } + + public async setBlockTopic(channelId: string, topicId: string): Promise { + } + + public async setBlockTag(channelId: string, topicId: string, tagId: string): Promise { + } + + public async clearBlockTopic(channelId: string, topicId: string): Promise { + } + + public async clearBlockTag(channelId: string, topicId: string, tagId: string): Promise { + } + + public async getBlockedTopics(): Promise<{ channelId: string, topicId: string }[]> { + return []; + } + + public async getBlockedTags(): Promise<{ channelId: string, topicId: string, tagId: string }[]> { + return []; + } + + public getTopicAssetUrl(channelId: string, topicId: string, assetId: string): string { + return ''; + } + + public async getTopics(channelId: string): Promise { + return []; + } + + public async getMoreTopics(channelId: string): Promise { + return []; + } + + public async getTags(channelId: string, topicId: string): Promise { + return []; + } + + public async getMoreTags(channelId: string, topicId: string): Promise { + return []; + } + + public async setUnreadChannel(channelId: string): Promise { + } + + public async clearUnreadChannel(channelId: string): Promise { + } + + public async addRepeaterAccess(channelId: string, name: string): Promise { + return { id: '', guid: '', name: '', server: '', token: '' }; + } + + public async removeRepeaterAccess(channelId: string, repeaterId: string): Promise { + } +} + diff --git a/app/sdk/__mocks__/identity.ts b/app/sdk/__mocks__/identity.ts new file mode 100644 index 00000000..e57f3dea --- /dev/null +++ b/app/sdk/__mocks__/identity.ts @@ -0,0 +1,43 @@ +import { EventEmitter } from 'eventemitter3'; +import { type Identity } from '../src/api'; +import { type Profile } from '../src/types'; + +export class MockIdentityModule implements Identity { + + public revision: number; + private emitter: EventEmitter; + + constructor() { + this.revision = 0; + this.emitter = new EventEmitter(); + } + + public addProfileListener(ev: (profile: Profile) => void): void { + this.emitter.on('profile', ev); + } + + public removeProfileListener(ev: (profile: Profile) => void): void { + this.emitter.off('profile', ev); + } + + public close(): void { + } + + public async setRevision(rev: number): Promise { + this.revision = rev; + } + + public async setProfileData(name: string, location: string, description: string): Promise { + } + + public async setProfileImage(image: string): Promise { + } + + public async getHandleStatus(handle: string): Promise { + } + + public getProfileImageUrl(): string { + return ''; + } +} + diff --git a/app/sdk/__mocks__/waitFor.ts b/app/sdk/__mocks__/waitFor.ts new file mode 100644 index 00000000..ae4e5400 --- /dev/null +++ b/app/sdk/__mocks__/waitFor.ts @@ -0,0 +1,10 @@ +export async function waitFor(cond: () => boolean, sec: number = 1): Promise { + for (let i = 0; i < sec * 10; i++) { + if (cond()) { + return; + } + await new Promise(r => setTimeout(r, 100)); + } + expect(cond()).toBe(true); +} + diff --git a/app/sdk/__tests__/session.tests.ts b/app/sdk/__tests__/session.tests.ts index d8460439..a171fff5 100644 --- a/app/sdk/__tests__/session.tests.ts +++ b/app/sdk/__tests__/session.tests.ts @@ -2,12 +2,73 @@ import { DatabagSDK } from '../src/index'; import { type SessionParams } from '../src/types'; import { MockConnection } from '../__mocks__/connection'; +import { MockAccountModule } from '../__mocks__/account'; +import { MockIdentityModule } from '../__mocks__/identity'; +import { MockAliasModule } from '../__mocks__/alias'; +import { MockContentModule } from '../__mocks__/content'; +import { MockContactModule } from '../__mocks__/contact'; +import { MockAttributeModule } from '../__mocks__/attribute'; +import { waitFor } from '../__mocks__/waitFor'; -const mock = new MockConnection(); +const mockConnection = new MockConnection(); jest.mock('../src/connection', () => { return { Connection: jest.fn().mockImplementation(() => { - return mock; + return mockConnection; + }) + } +}) + +const mockAccount = new MockAccountModule(); +jest.mock('../src/account', () => { + return { + AccountModule: jest.fn().mockImplementation(() => { + return mockAccount; + }) + } +}) + +const mockIdentity = new MockIdentityModule(); +jest.mock('../src/identity', () => { + return { + IdentityModule: jest.fn().mockImplementation(() => { + return mockIdentity; + }) + } +}) + +const mockContent = new MockContentModule(); +jest.mock('../src/content', () => { + return { + ContentModule: jest.fn().mockImplementation(() => { + return mockContent; + }) + } +}) + +const mockContact = new MockContactModule(); +jest.mock('../src/contact', () => { + return { + ContactModule: jest.fn().mockImplementation(() => { + return mockContact; + }) + } +}) + +const mockAttribute = new MockAttributeModule(); +jest.mock('../src/attribute', () => { + return { + AttributeModule: jest.fn().mockImplementation(() => { + return mockAttribute; + }) + } +}) + +const mockAlias = new MockAliasModule(); +jest.mock('../src/alias', () => { + return { + AliasModule: jest.fn().mockImplementation(() => { + return mockAlias; }) } }) @@ -21,7 +82,13 @@ test('allocates session correctly', async () => { session.addStatusListener((ev: string) => { status = ev; }); const account = session.getAccount(); account.enableNotifications(); - mock.emitStatus('connected'); - mock.emitRevision({ account: 0, profile: 0, article: 0, group: 0, channel: 0, card: 0}); - expect(status).toBe('connected'); + mockConnection.emitStatus('connected'); + mockConnection.emitRevision({ account: 3, profile: 3, article: 3, group: 3, channel: 3, card: 3}); + await waitFor(() => (status === 'connected')); + await waitFor(() => (mockAccount.revision == 3)); + await waitFor(() => (mockIdentity.revision == 3)); + await waitFor(() => (mockContent.revision == 3)); + await waitFor(() => (mockContact.revision == 3)); + await waitFor(() => (mockAttribute.revision == 3)); + await waitFor(() => (mockAlias.revision == 3)); });