Unit Testing (#35)
* add testing lib * remove coverage folder from git * finished basic test setup * fix tests typescript and import paths * add first snapshot * testing utils * rename test files; update script flags; ++tests * testing utils functions * testing downloadAndResize wip * remove download test * specify unwanted coverage paths; remove update snapshots flag * fix strings tests * testing downloadAndResize method * increasing testing * fixing snapshots wip * fixed shell mobile snapshot * adding snapshots for the screens * fix onboard snapshot * fix typescript issues * fix TabsSelector snapshot * Account for testing device's locale in ago() tests * Remove platform detection on regex * mocking store state wip * mocking store state * increasing test coverage * increasing test coverage * increasing test coverage on src/screens * src/screens (except for profile) above 80% cov * testing profile screen wip * increase coverage on Menu and TabsSelector * mocking profile ui state wip * mocking profile ui state wip * fixing mobileshell tests wip * snapshots using testing-library * fixing profile tests wip * removing mobile shell tests * src/view/com tests wip * remove unnecessary patch-package * fixed profile test error * clear mocks after every test * fix base mocked store values (getters) * fix base mocked store values (hasLoaded, nonReplyFeed) * profile screen above 80% coverage * testing custom hooks * improving composer coverage * fix tests after merge * finishing composer coverage * improving src/com/discover coverage * improve src/view/com/login coverage fix SuggestedFollows tests adding some comments * fix SuggestedFollows tests * improve src/view/com/profile coverage extra minor fixes * improve src/view/com/notifications coverage * update coverage ignore patterns * rename errorMessageTryAgainButton increase SuggestedFollows converage * improve src/view/com/posts coverage * improve src/view/com/onboard coverage * update snapshot * improve src/view/com/post coverage * improve src/view/com/post-thread coverage rename ErrorMessage tests test Debug and Log components * init testing state * testing root-store * updating comments * small fixes * removed extra console logs * improve src/state/models coverage refactor rootStore rename some spies * adding cleanup method after tests * improve src/state/models coverage * improve src/state/models coverage * improve src/state/models coverage * improve src/state/models coverage * test setInterval in setupState * Clean up tests and update Home screen state management * Remove some tests we dont need * Remove snapshot tests * Remove any tests that dont demonstrate clear value * Cleanup Co-authored-by: Paul Frazee <pfrazee@gmail.com>
This commit is contained in:
parent
11c861d2d3
commit
5abcc8e336
95 changed files with 2852 additions and 9936 deletions
72
__tests__/state/models/link-metas-view.test.ts
Normal file
72
__tests__/state/models/link-metas-view.test.ts
Normal file
|
@ -0,0 +1,72 @@
|
|||
import {RootStoreModel} from '../../../src/state/models/root-store'
|
||||
import {LinkMetasViewModel} from '../../../src/state/models/link-metas-view'
|
||||
import * as LinkMetaLib from '../../../src/lib/link-meta'
|
||||
import {LikelyType} from './../../../src/lib/link-meta'
|
||||
import {sessionClient, SessionServiceClient} from '@atproto/api'
|
||||
import {DEFAULT_SERVICE} from '../../../src/state'
|
||||
|
||||
describe('LinkMetasViewModel', () => {
|
||||
let viewModel: LinkMetasViewModel
|
||||
let rootStore: RootStoreModel
|
||||
|
||||
const getLinkMetaMockSpy = jest.spyOn(LinkMetaLib, 'getLinkMeta')
|
||||
const mockedMeta = {
|
||||
title: 'Test Title',
|
||||
url: 'testurl',
|
||||
likelyType: LikelyType.Other,
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
const api = sessionClient.service(DEFAULT_SERVICE) as SessionServiceClient
|
||||
rootStore = new RootStoreModel(api)
|
||||
viewModel = new LinkMetasViewModel(rootStore)
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
describe('getLinkMeta', () => {
|
||||
it('should return link meta if it is cached', async () => {
|
||||
const url = 'http://example.com'
|
||||
|
||||
viewModel.cache.set(url, mockedMeta)
|
||||
|
||||
const result = await viewModel.getLinkMeta(url)
|
||||
|
||||
expect(getLinkMetaMockSpy).not.toHaveBeenCalled()
|
||||
expect(result).toEqual(mockedMeta)
|
||||
})
|
||||
|
||||
it('should return link meta if it is not cached', async () => {
|
||||
getLinkMetaMockSpy.mockResolvedValueOnce(mockedMeta)
|
||||
|
||||
const result = await viewModel.getLinkMeta(mockedMeta.url)
|
||||
|
||||
expect(getLinkMetaMockSpy).toHaveBeenCalledWith(mockedMeta.url)
|
||||
expect(result).toEqual(mockedMeta)
|
||||
})
|
||||
|
||||
it('should cache the link meta if it is successfully returned', async () => {
|
||||
getLinkMetaMockSpy.mockResolvedValueOnce(mockedMeta)
|
||||
|
||||
await viewModel.getLinkMeta(mockedMeta.url)
|
||||
|
||||
expect(viewModel.cache.get(mockedMeta.url)).toEqual(mockedMeta)
|
||||
})
|
||||
|
||||
it('should not cache the link meta if it fails to return', async () => {
|
||||
const url = 'http://example.com'
|
||||
const error = new Error('Failed to fetch link meta')
|
||||
getLinkMetaMockSpy.mockRejectedValueOnce(error)
|
||||
|
||||
try {
|
||||
await viewModel.getLinkMeta(url)
|
||||
fail('Error was not thrown')
|
||||
} catch (e) {
|
||||
expect(e).toEqual(error)
|
||||
expect(viewModel.cache.get(url)).toBeUndefined()
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
153
__tests__/state/models/log.test.ts
Normal file
153
__tests__/state/models/log.test.ts
Normal file
|
@ -0,0 +1,153 @@
|
|||
import {LogModel} from '../../../src/state/models/log'
|
||||
|
||||
describe('LogModel', () => {
|
||||
let logModel: LogModel
|
||||
|
||||
beforeEach(() => {
|
||||
logModel = new LogModel()
|
||||
jest.spyOn(console, 'debug')
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
it('should call a log method and add a log entry to the entries array', () => {
|
||||
logModel.debug('Test log')
|
||||
expect(logModel.entries.length).toEqual(1)
|
||||
expect(logModel.entries[0]).toEqual({
|
||||
id: logModel.entries[0].id,
|
||||
type: 'debug',
|
||||
summary: 'Test log',
|
||||
details: undefined,
|
||||
ts: logModel.entries[0].ts,
|
||||
})
|
||||
|
||||
logModel.warn('Test log')
|
||||
expect(logModel.entries.length).toEqual(2)
|
||||
expect(logModel.entries[1]).toEqual({
|
||||
id: logModel.entries[1].id,
|
||||
type: 'warn',
|
||||
summary: 'Test log',
|
||||
details: undefined,
|
||||
ts: logModel.entries[1].ts,
|
||||
})
|
||||
|
||||
logModel.error('Test log')
|
||||
expect(logModel.entries.length).toEqual(3)
|
||||
expect(logModel.entries[2]).toEqual({
|
||||
id: logModel.entries[2].id,
|
||||
type: 'error',
|
||||
summary: 'Test log',
|
||||
details: undefined,
|
||||
ts: logModel.entries[2].ts,
|
||||
})
|
||||
})
|
||||
|
||||
it('should call the console.debug after calling the debug method', () => {
|
||||
logModel.debug('Test log')
|
||||
expect(console.debug).toHaveBeenCalledWith('Test log', '')
|
||||
})
|
||||
|
||||
it('should call the serialize method', () => {
|
||||
logModel.debug('Test log')
|
||||
expect(logModel.serialize()).toEqual({
|
||||
entries: [
|
||||
{
|
||||
id: logModel.entries[0].id,
|
||||
type: 'debug',
|
||||
summary: 'Test log',
|
||||
details: undefined,
|
||||
ts: logModel.entries[0].ts,
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
it('should call the hydrate method with valid properties', () => {
|
||||
logModel.hydrate({
|
||||
entries: [
|
||||
{
|
||||
id: '123',
|
||||
type: 'debug',
|
||||
summary: 'Test log',
|
||||
details: undefined,
|
||||
ts: 123,
|
||||
},
|
||||
],
|
||||
})
|
||||
expect(logModel.entries).toEqual([
|
||||
{
|
||||
id: '123',
|
||||
type: 'debug',
|
||||
summary: 'Test log',
|
||||
details: undefined,
|
||||
ts: 123,
|
||||
},
|
||||
])
|
||||
})
|
||||
|
||||
it('should call the hydrate method with invalid properties', () => {
|
||||
logModel.hydrate({
|
||||
entries: [
|
||||
{
|
||||
id: '123',
|
||||
type: 'debug',
|
||||
summary: 'Test log',
|
||||
details: undefined,
|
||||
ts: 123,
|
||||
},
|
||||
{
|
||||
summary: 'Invalid entry',
|
||||
},
|
||||
],
|
||||
})
|
||||
expect(logModel.entries).toEqual([
|
||||
{
|
||||
id: '123',
|
||||
type: 'debug',
|
||||
summary: 'Test log',
|
||||
details: undefined,
|
||||
ts: 123,
|
||||
},
|
||||
])
|
||||
})
|
||||
|
||||
it('should stringify the details if it is not a string', () => {
|
||||
logModel.debug('Test log', {details: 'test'})
|
||||
expect(logModel.entries[0].details).toEqual('{\n "details": "test"\n}')
|
||||
})
|
||||
|
||||
it('should stringify the details object if it is of a specific error', () => {
|
||||
class TestError extends Error {
|
||||
constructor() {
|
||||
super()
|
||||
this.name = 'TestError'
|
||||
}
|
||||
}
|
||||
const error = new TestError()
|
||||
logModel.error('Test error log', error)
|
||||
expect(logModel.entries[0].details).toEqual('TestError')
|
||||
|
||||
class XRPCInvalidResponseErrorMock {
|
||||
validationError = {toString: () => 'validationError'}
|
||||
lexiconNsid = 'test'
|
||||
}
|
||||
const xrpcInvalidResponseError = new XRPCInvalidResponseErrorMock()
|
||||
logModel.error('Test error log', xrpcInvalidResponseError)
|
||||
expect(logModel.entries[1].details).toEqual(
|
||||
'{\n "validationError": {},\n "lexiconNsid": "test"\n}',
|
||||
)
|
||||
|
||||
class XRPCErrorMock {
|
||||
status = 'status'
|
||||
error = 'error'
|
||||
message = 'message'
|
||||
}
|
||||
const xrpcError = new XRPCErrorMock()
|
||||
logModel.error('Test error log', xrpcError)
|
||||
expect(logModel.entries[2].details).toEqual(
|
||||
'{\n "status": "status",\n "error": "error",\n "message": "message"\n}',
|
||||
)
|
||||
})
|
||||
})
|
183
__tests__/state/models/me.test.ts
Normal file
183
__tests__/state/models/me.test.ts
Normal file
|
@ -0,0 +1,183 @@
|
|||
import {RootStoreModel} from '../../../src/state/models/root-store'
|
||||
import {MeModel} from '../../../src/state/models/me'
|
||||
import {MembershipsViewModel} from './../../../src/state/models/memberships-view'
|
||||
import {NotificationsViewModel} from './../../../src/state/models/notifications-view'
|
||||
import {sessionClient, SessionServiceClient} from '@atproto/api'
|
||||
import {DEFAULT_SERVICE} from './../../../src/state/index'
|
||||
|
||||
describe('MeModel', () => {
|
||||
let rootStore: RootStoreModel
|
||||
let meModel: MeModel
|
||||
|
||||
beforeEach(() => {
|
||||
const api = sessionClient.service(DEFAULT_SERVICE) as SessionServiceClient
|
||||
rootStore = new RootStoreModel(api)
|
||||
meModel = new MeModel(rootStore)
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
it('should clear() correctly', () => {
|
||||
meModel.did = '123'
|
||||
meModel.handle = 'handle'
|
||||
meModel.displayName = 'John Doe'
|
||||
meModel.description = 'description'
|
||||
meModel.avatar = 'avatar'
|
||||
meModel.notificationCount = 1
|
||||
meModel.clear()
|
||||
expect(meModel.did).toEqual('')
|
||||
expect(meModel.handle).toEqual('')
|
||||
expect(meModel.displayName).toEqual('')
|
||||
expect(meModel.description).toEqual('')
|
||||
expect(meModel.avatar).toEqual('')
|
||||
expect(meModel.notificationCount).toEqual(0)
|
||||
expect(meModel.memberships).toBeUndefined()
|
||||
})
|
||||
|
||||
it('should hydrate() successfully with valid properties', () => {
|
||||
meModel.hydrate({
|
||||
did: '123',
|
||||
handle: 'handle',
|
||||
displayName: 'John Doe',
|
||||
description: 'description',
|
||||
avatar: 'avatar',
|
||||
})
|
||||
expect(meModel.did).toEqual('123')
|
||||
expect(meModel.handle).toEqual('handle')
|
||||
expect(meModel.displayName).toEqual('John Doe')
|
||||
expect(meModel.description).toEqual('description')
|
||||
expect(meModel.avatar).toEqual('avatar')
|
||||
})
|
||||
|
||||
it('should not hydrate() with invalid properties', () => {
|
||||
meModel.hydrate({
|
||||
did: '',
|
||||
handle: 'handle',
|
||||
displayName: 'John Doe',
|
||||
description: 'description',
|
||||
avatar: 'avatar',
|
||||
})
|
||||
expect(meModel.did).toEqual('')
|
||||
expect(meModel.handle).toEqual('')
|
||||
expect(meModel.displayName).toEqual('')
|
||||
expect(meModel.description).toEqual('')
|
||||
expect(meModel.avatar).toEqual('')
|
||||
|
||||
meModel.hydrate({
|
||||
did: '123',
|
||||
displayName: 'John Doe',
|
||||
description: 'description',
|
||||
avatar: 'avatar',
|
||||
})
|
||||
expect(meModel.did).toEqual('')
|
||||
expect(meModel.handle).toEqual('')
|
||||
expect(meModel.displayName).toEqual('')
|
||||
expect(meModel.description).toEqual('')
|
||||
expect(meModel.avatar).toEqual('')
|
||||
})
|
||||
|
||||
it('should load() successfully', async () => {
|
||||
jest
|
||||
.spyOn(rootStore.api.app.bsky.actor, 'getProfile')
|
||||
.mockImplementationOnce((): Promise<any> => {
|
||||
return Promise.resolve({
|
||||
data: {
|
||||
displayName: 'John Doe',
|
||||
description: 'description',
|
||||
avatar: 'avatar',
|
||||
},
|
||||
})
|
||||
})
|
||||
rootStore.session.data = {
|
||||
did: '123',
|
||||
handle: 'handle',
|
||||
service: 'test service',
|
||||
accessJwt: 'test token',
|
||||
refreshJwt: 'test token',
|
||||
}
|
||||
await meModel.load()
|
||||
expect(meModel.did).toEqual('123')
|
||||
expect(meModel.handle).toEqual('handle')
|
||||
expect(meModel.displayName).toEqual('John Doe')
|
||||
expect(meModel.description).toEqual('description')
|
||||
expect(meModel.avatar).toEqual('avatar')
|
||||
})
|
||||
|
||||
it('should load() successfully without profile data', async () => {
|
||||
jest
|
||||
.spyOn(rootStore.api.app.bsky.actor, 'getProfile')
|
||||
.mockImplementationOnce((): Promise<any> => {
|
||||
return Promise.resolve({
|
||||
data: null,
|
||||
})
|
||||
})
|
||||
rootStore.session.data = {
|
||||
did: '123',
|
||||
handle: 'handle',
|
||||
service: 'test service',
|
||||
accessJwt: 'test token',
|
||||
refreshJwt: 'test token',
|
||||
}
|
||||
await meModel.load()
|
||||
expect(meModel.did).toEqual('123')
|
||||
expect(meModel.handle).toEqual('handle')
|
||||
expect(meModel.displayName).toEqual('')
|
||||
expect(meModel.description).toEqual('')
|
||||
expect(meModel.avatar).toEqual('')
|
||||
})
|
||||
|
||||
it('should load() to nothing when no session', async () => {
|
||||
rootStore.session.data = null
|
||||
await meModel.load()
|
||||
expect(meModel.did).toEqual('')
|
||||
expect(meModel.handle).toEqual('')
|
||||
expect(meModel.displayName).toEqual('')
|
||||
expect(meModel.description).toEqual('')
|
||||
expect(meModel.avatar).toEqual('')
|
||||
expect(meModel.notificationCount).toEqual(0)
|
||||
expect(meModel.memberships).toBeUndefined()
|
||||
})
|
||||
|
||||
it('should serialize() key information', () => {
|
||||
meModel.did = '123'
|
||||
meModel.handle = 'handle'
|
||||
meModel.displayName = 'John Doe'
|
||||
meModel.description = 'description'
|
||||
meModel.avatar = 'avatar'
|
||||
|
||||
expect(meModel.serialize()).toEqual({
|
||||
did: '123',
|
||||
handle: 'handle',
|
||||
displayName: 'John Doe',
|
||||
description: 'description',
|
||||
avatar: 'avatar',
|
||||
})
|
||||
})
|
||||
|
||||
it('should clearNotificationCount() successfully', () => {
|
||||
meModel.clearNotificationCount()
|
||||
expect(meModel.notificationCount).toBe(0)
|
||||
})
|
||||
|
||||
it('should update notifs count with fetchStateUpdate()', async () => {
|
||||
meModel.notifications = {
|
||||
refresh: jest.fn(),
|
||||
} as unknown as NotificationsViewModel
|
||||
|
||||
jest
|
||||
.spyOn(rootStore.api.app.bsky.notification, 'getCount')
|
||||
.mockImplementationOnce((): Promise<any> => {
|
||||
return Promise.resolve({
|
||||
data: {
|
||||
count: 1,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
await meModel.fetchStateUpdate()
|
||||
expect(meModel.notificationCount).toBe(1)
|
||||
expect(meModel.notifications.refresh).toHaveBeenCalled()
|
||||
})
|
||||
})
|
154
__tests__/state/models/navigation.test.ts
Normal file
154
__tests__/state/models/navigation.test.ts
Normal file
|
@ -0,0 +1,154 @@
|
|||
import {
|
||||
NavigationModel,
|
||||
NavigationTabModel,
|
||||
} from './../../../src/state/models/navigation'
|
||||
import * as flags from '../../../src/build-flags'
|
||||
|
||||
describe('NavigationModel', () => {
|
||||
let model: NavigationModel
|
||||
|
||||
beforeEach(() => {
|
||||
model = new NavigationModel()
|
||||
model.setTitle([0, 0], 'title')
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
it('should clear() to the correct base state', async () => {
|
||||
await model.clear()
|
||||
expect(model.tabCount).toBe(2)
|
||||
expect(model.tab).toEqual({
|
||||
fixedTabPurpose: 0,
|
||||
history: [
|
||||
{
|
||||
id: expect.anything(),
|
||||
ts: expect.anything(),
|
||||
url: '/',
|
||||
},
|
||||
],
|
||||
id: expect.anything(),
|
||||
index: 0,
|
||||
isNewTab: false,
|
||||
})
|
||||
})
|
||||
|
||||
it('should call the navigate method', async () => {
|
||||
const navigateSpy = jest.spyOn(model.tab, 'navigate')
|
||||
await model.navigate('testurl', 'teststring')
|
||||
expect(navigateSpy).toHaveBeenCalledWith('testurl', 'teststring')
|
||||
})
|
||||
|
||||
it('should call the refresh method', async () => {
|
||||
const refreshSpy = jest.spyOn(model.tab, 'refresh')
|
||||
await model.refresh()
|
||||
expect(refreshSpy).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should call the isCurrentScreen method', () => {
|
||||
expect(model.isCurrentScreen(11, 0)).toEqual(false)
|
||||
})
|
||||
|
||||
it('should call the tab getter', () => {
|
||||
expect(model.tab).toEqual({
|
||||
fixedTabPurpose: 0,
|
||||
history: [
|
||||
{
|
||||
id: expect.anything(),
|
||||
ts: expect.anything(),
|
||||
url: '/',
|
||||
},
|
||||
],
|
||||
id: expect.anything(),
|
||||
index: 0,
|
||||
isNewTab: false,
|
||||
})
|
||||
})
|
||||
|
||||
it('should call the tabCount getter', () => {
|
||||
expect(model.tabCount).toBe(2)
|
||||
})
|
||||
|
||||
describe('tabs not enabled', () => {
|
||||
jest.mock('../../../src/build-flags', () => ({
|
||||
TABS_ENABLED: false,
|
||||
}))
|
||||
|
||||
afterAll(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
it('should not create new tabs', () => {
|
||||
// @ts-expect-error
|
||||
flags.TABS_ENABLED = false
|
||||
model.newTab('testurl')
|
||||
expect(model.tab.isNewTab).toBe(false)
|
||||
expect(model.tabIndex).toBe(0)
|
||||
})
|
||||
|
||||
it('should not change the active tab', () => {
|
||||
// @ts-expect-error
|
||||
flags.TABS_ENABLED = false
|
||||
model.setActiveTab(2)
|
||||
expect(model.tabIndex).toBe(0)
|
||||
})
|
||||
|
||||
it('should note close tabs', () => {
|
||||
// @ts-expect-error
|
||||
flags.TABS_ENABLED = false
|
||||
model.closeTab(0)
|
||||
expect(model.tabCount).toBe(2)
|
||||
})
|
||||
})
|
||||
|
||||
describe('tabs enabled', () => {
|
||||
jest.mock('../../../src/build-flags', () => ({
|
||||
TABS_ENABLED: true,
|
||||
}))
|
||||
|
||||
afterAll(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
it('should create new tabs', () => {
|
||||
// @ts-expect-error
|
||||
flags.TABS_ENABLED = true
|
||||
|
||||
model.newTab('testurl', 'title')
|
||||
expect(model.tab.isNewTab).toBe(true)
|
||||
expect(model.tabIndex).toBe(2)
|
||||
})
|
||||
|
||||
it('should change the current tab', () => {
|
||||
// @ts-expect-error
|
||||
flags.TABS_ENABLED = true
|
||||
|
||||
model.setActiveTab(0)
|
||||
expect(model.tabIndex).toBe(0)
|
||||
})
|
||||
|
||||
it('should close tabs', () => {
|
||||
// @ts-expect-error
|
||||
flags.TABS_ENABLED = true
|
||||
|
||||
model.closeTab(0)
|
||||
expect(model.tabs).toEqual([
|
||||
{
|
||||
fixedTabPurpose: 1,
|
||||
history: [
|
||||
{
|
||||
id: expect.anything(),
|
||||
ts: expect.anything(),
|
||||
url: '/notifications',
|
||||
},
|
||||
],
|
||||
id: expect.anything(),
|
||||
index: 0,
|
||||
isNewTab: false,
|
||||
},
|
||||
])
|
||||
expect(model.tabIndex).toBe(0)
|
||||
})
|
||||
})
|
||||
})
|
46
__tests__/state/models/onboard.test.ts
Normal file
46
__tests__/state/models/onboard.test.ts
Normal file
|
@ -0,0 +1,46 @@
|
|||
import {
|
||||
OnboardModel,
|
||||
OnboardStageOrder,
|
||||
} from '../../../src/state/models/onboard'
|
||||
|
||||
describe('OnboardModel', () => {
|
||||
let onboardModel: OnboardModel
|
||||
|
||||
beforeEach(() => {
|
||||
onboardModel = new OnboardModel()
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
it('should start/stop correctly', () => {
|
||||
onboardModel.start()
|
||||
expect(onboardModel.isOnboarding).toBe(true)
|
||||
onboardModel.stop()
|
||||
expect(onboardModel.isOnboarding).toBe(false)
|
||||
})
|
||||
|
||||
it('should call the next method until it has no more stages', () => {
|
||||
onboardModel.start()
|
||||
onboardModel.next()
|
||||
expect(onboardModel.stage).toBe(OnboardStageOrder[1])
|
||||
|
||||
onboardModel.next()
|
||||
expect(onboardModel.isOnboarding).toBe(false)
|
||||
expect(onboardModel.stage).toBe(OnboardStageOrder[0])
|
||||
})
|
||||
|
||||
it('serialize and hydrate', () => {
|
||||
const serialized = onboardModel.serialize()
|
||||
const newModel = new OnboardModel()
|
||||
newModel.hydrate(serialized)
|
||||
expect(newModel).toEqual(onboardModel)
|
||||
|
||||
onboardModel.start()
|
||||
onboardModel.next()
|
||||
const serialized2 = onboardModel.serialize()
|
||||
newModel.hydrate(serialized2)
|
||||
expect(newModel).toEqual(onboardModel)
|
||||
})
|
||||
})
|
73
__tests__/state/models/root-store.test.ts
Normal file
73
__tests__/state/models/root-store.test.ts
Normal file
|
@ -0,0 +1,73 @@
|
|||
import {RootStoreModel} from '../../../src/state/models/root-store'
|
||||
import {setupState} from '../../../src/state'
|
||||
|
||||
describe('rootStore', () => {
|
||||
let rootStore: RootStoreModel
|
||||
|
||||
beforeAll(() => {
|
||||
jest.useFakeTimers()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
rootStore = await setupState()
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
it('resolveName() handles inputs correctly', () => {
|
||||
const spyMethod = jest
|
||||
.spyOn(rootStore.api.com.atproto.handle, 'resolve')
|
||||
.mockResolvedValue({success: true, headers: {}, data: {did: 'testdid'}})
|
||||
|
||||
rootStore.resolveName('teststring')
|
||||
expect(spyMethod).toHaveBeenCalledWith({handle: 'teststring'})
|
||||
|
||||
expect(rootStore.resolveName('')).rejects.toThrow('Invalid handle: ""')
|
||||
|
||||
expect(rootStore.resolveName('did:123')).resolves.toReturnWith('did:123')
|
||||
})
|
||||
|
||||
it('should call the clearAll() resets state correctly', () => {
|
||||
rootStore.clearAll()
|
||||
|
||||
expect(rootStore.session.data).toEqual(null)
|
||||
expect(rootStore.nav.tabs).toEqual([
|
||||
{
|
||||
fixedTabPurpose: 0,
|
||||
history: [
|
||||
{
|
||||
id: expect.anything(),
|
||||
ts: expect.anything(),
|
||||
url: '/',
|
||||
},
|
||||
],
|
||||
id: expect.anything(),
|
||||
index: 0,
|
||||
isNewTab: false,
|
||||
},
|
||||
{
|
||||
fixedTabPurpose: 1,
|
||||
history: [
|
||||
{
|
||||
id: expect.anything(),
|
||||
ts: expect.anything(),
|
||||
url: '/notifications',
|
||||
},
|
||||
],
|
||||
id: expect.anything(),
|
||||
index: 0,
|
||||
isNewTab: false,
|
||||
},
|
||||
])
|
||||
expect(rootStore.nav.tabIndex).toEqual(0)
|
||||
expect(rootStore.me.did).toEqual('')
|
||||
expect(rootStore.me.handle).toEqual('')
|
||||
expect(rootStore.me.displayName).toEqual('')
|
||||
expect(rootStore.me.description).toEqual('')
|
||||
expect(rootStore.me.avatar).toEqual('')
|
||||
expect(rootStore.me.notificationCount).toEqual(0)
|
||||
expect(rootStore.me.memberships).toBeUndefined()
|
||||
})
|
||||
})
|
59
__tests__/state/models/shell-ui.test.ts
Normal file
59
__tests__/state/models/shell-ui.test.ts
Normal file
|
@ -0,0 +1,59 @@
|
|||
import {
|
||||
ConfirmModal,
|
||||
ImageLightbox,
|
||||
ShellUiModel,
|
||||
} from './../../../src/state/models/shell-ui'
|
||||
|
||||
describe('ShellUiModel', () => {
|
||||
let model: ShellUiModel
|
||||
|
||||
beforeEach(() => {
|
||||
model = new ShellUiModel()
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
it('should call the openModal & closeModal method', () => {
|
||||
model.openModal(ConfirmModal)
|
||||
expect(model.isModalActive).toEqual(true)
|
||||
expect(model.activeModal).toEqual(ConfirmModal)
|
||||
|
||||
model.closeModal()
|
||||
expect(model.isModalActive).toEqual(false)
|
||||
expect(model.activeModal).toBeUndefined()
|
||||
})
|
||||
|
||||
it('should call the openLightbox & closeLightbox method', () => {
|
||||
model.openLightbox(new ImageLightbox('uri'))
|
||||
expect(model.isLightboxActive).toEqual(true)
|
||||
expect(model.activeLightbox).toEqual(new ImageLightbox('uri'))
|
||||
|
||||
model.closeLightbox()
|
||||
expect(model.isLightboxActive).toEqual(false)
|
||||
expect(model.activeLightbox).toBeUndefined()
|
||||
})
|
||||
|
||||
it('should call the openComposer & closeComposer method', () => {
|
||||
const composer = {
|
||||
replyTo: {
|
||||
uri: 'uri',
|
||||
cid: 'cid',
|
||||
text: 'text',
|
||||
author: {
|
||||
handle: 'handle',
|
||||
displayName: 'name',
|
||||
},
|
||||
},
|
||||
onPost: jest.fn(),
|
||||
}
|
||||
model.openComposer(composer)
|
||||
expect(model.isComposerActive).toEqual(true)
|
||||
expect(model.composerOpts).toEqual(composer)
|
||||
|
||||
model.closeComposer()
|
||||
expect(model.isComposerActive).toEqual(false)
|
||||
expect(model.composerOpts).toBeUndefined()
|
||||
})
|
||||
})
|
Loading…
Add table
Add a link
Reference in a new issue