Files
yinxin630--fiora/packages/web/test/state/reducer.spec.ts
T
2026-07-13 12:27:50 +08:00

590 lines
17 KiB
TypeScript

import getFriendId from '@fiora/utils/getFriendId';
import reducer, { State, initialState } from '../../src/state/reducer';
import { Action, ActionTypes } from '../../src/state/action';
describe('redux reducer', () => {
it('should user initial state', () => {
const action = { type: 'mock' as ActionTypes, payload: {} } as Action;
expect(reducer(undefined, action)).toBe(initialState);
});
it('should return origin state with unknown action', () => {
const state = {} as State;
const action = { type: 'mock' as ActionTypes, payload: {} } as Action;
expect(reducer(state, action)).toBe(state);
});
it('should set connect status to true', () => {
const state = {
connect: false,
} as State;
const action = {
type: ActionTypes.Connect,
payload: {},
};
const newState = reducer(state, action);
expect(newState.connect).toBe(true);
});
it('should set connect status to false', () => {
const state = {
connect: true,
} as State;
const action = {
type: ActionTypes.Disconnect,
payload: {},
};
const newState = reducer(state, action);
expect(newState.connect).toBe(false);
});
it('should set guest user and default group', () => {
const state = {} as State;
const group = {
_id: '1',
name: 'Default Group',
};
const action = {
type: ActionTypes.SetGuest,
payload: group,
};
const newState = reducer(state, action);
expect(newState.user).not.toBe(null);
expect(newState.linkmans[group._id]).toBe(group);
expect(newState.focus).toBe(group._id);
});
it('should set user and linkmans', () => {
const state = {
linkmans: {},
} as State;
const group = {
_id: 'group',
name: 'group',
};
const friend = {
from: '111',
to: {
_id: '222',
username: 'friend',
},
};
const action = {
type: ActionTypes.SetUser,
payload: {
_id: 'id',
username: 'user',
friends: [friend],
groups: [group],
},
};
const newState = reducer(state, action);
expect(newState.user).not.toBe(null);
expect(Object.keys(newState.linkmans).length).toBe(2);
expect(newState.linkmans[group._id].type).toBe('group');
const friendId = getFriendId(friend.from, friend.to._id);
expect(newState.linkmans[friendId].type).toBe('friend');
expect(newState.linkmans[friendId].name).toBe(friend.to.username);
expect(newState.focus).toBe(group._id);
});
it('should update user with payload data', () => {
const state = {
user: {
_id: 'id',
username: 'name',
},
} as State;
const action = {
type: ActionTypes.UpdateUserInfo,
payload: {
username: 'new',
},
};
const newState = reducer(state, action);
expect(newState.user?.username).toBe('new');
});
it('should set user to null', () => {
const state = {
user: {
_id: 'id',
},
} as State;
const action = {
type: ActionTypes.Logout,
payload: {},
};
const newState = reducer(state, action);
expect(newState.user).toEqual(null);
});
it('should update user avatar', () => {
const state = {
user: {
_id: 'id',
avatar: 'avatar',
},
} as State;
const action = {
type: ActionTypes.SetAvatar,
payload: 'new',
};
const newState = reducer(state, action);
expect(newState.user?.avatar).toBe('new');
});
it('should update focus and reduce exist messages when more than 50', () => {
const linkman = {
_id: '1',
messages: {},
};
const state = {
linkmans: {
[linkman._id]: linkman,
},
focus: '',
} as State;
const action = {
type: ActionTypes.SetFocus,
payload: linkman._id,
};
const newState = reducer(state, action);
expect(newState.focus).toBe(linkman._id);
expect(
Object.keys(newState.linkmans[newState.focus].messages),
).toHaveLength(0);
});
it('should reduce exist messages when more than 50', () => {
const messages: { [id: string]: any } = {};
for (let i = 0; i < 51; i++) {
messages[i] = {
_id: i,
};
}
const linkman = {
_id: '1',
messages,
unread: 10,
};
const state = {
linkmans: {
[linkman._id]: linkman,
},
focus: '',
} as State;
const action = {
type: ActionTypes.SetFocus,
payload: linkman._id,
};
const newState = reducer(state, action);
expect(
Object.keys(newState.linkmans[newState.focus].messages),
).toHaveLength(50);
});
it('should be no change when foucs not exits user id', () => {
const linkman = {
id: '1',
};
// @ts-ignore
const state = {
linkmans: {
[linkman.id]: linkman,
},
focus: linkman.id,
} as State;
const action = {
type: ActionTypes.SetFocus,
payload: '2',
};
const newState = reducer(state, action);
expect(newState).toBe(state);
});
it('should add new group linkman into linkmans', () => {
const state = {
linkmans: {},
} as State;
const linkman = {
_id: 'id',
name: 'name',
type: 'group',
};
const action = {
type: ActionTypes.AddLinkman,
payload: {
linkman,
focus: true,
},
};
const newState = reducer(state, action);
expect(Object.keys(newState.linkmans)).toHaveLength(1);
expect(newState.focus).toBe(linkman._id);
});
it('should add new friend linkman into linkmans', () => {
const state = {
linkmans: {},
} as State;
const linkman = {
name: 'name',
type: 'friend',
from: '111',
to: {
_id: '222',
},
};
const action = {
type: ActionTypes.AddLinkman,
payload: {
linkman,
},
};
const newState = reducer(state, action);
expect(Object.keys(newState.linkmans)).toHaveLength(1);
expect(newState.linkmans['111222']).toBeTruthy();
});
it('should add new temporary linkman into linkmans', () => {
const state = {
linkmans: {},
} as State;
const linkman = {
_id: 'id',
name: 'name',
type: 'temporary',
};
const action = {
type: ActionTypes.AddLinkman,
payload: {
linkman,
},
};
const newState = reducer(state, action);
expect(Object.keys(newState.linkmans)).toHaveLength(1);
expect(newState.linkmans[linkman._id].unread).toBe(1);
});
it('should return origin state when add unknown linkman', () => {
const state = {
linkmans: {},
} as State;
const action = {
type: ActionTypes.AddLinkman,
payload: {
linkman: {
type: 'xxx',
},
},
};
const newState = reducer(state, action);
expect(newState).toBe(state);
});
it('should remove linkman form linkmans', () => {
const linkman1 = {
_id: '1',
};
const linkman2 = {
_id: '2',
};
const state = {
linkmans: {
[linkman1._id]: linkman1,
[linkman2._id]: linkman2,
},
} as State;
const action1 = {
type: ActionTypes.RemoveLinkman,
payload: linkman1._id,
};
const newState = reducer(state, action1);
expect(Object.keys(newState.linkmans)).toHaveLength(1);
expect(newState.focus).toBe(linkman2._id);
const action2 = {
type: ActionTypes.RemoveLinkman,
payload: linkman2._id,
};
expect(reducer(newState, action2).focus).toBe('');
});
it('should add messages to linkmans', () => {
const state = {
linkmans: {
1: {
_id: '1',
name: 'name',
messages: {},
},
2: {
_id: '2',
name: 'name',
messages: {},
},
},
} as unknown as State;
const action = {
type: ActionTypes.SetLinkmansLastMessages,
payload: {
'1': {
messages: [
{
_id: 'm1',
type: 'text',
content: 'content',
},
{
_id: 'm2',
type: 'text',
content: 'content',
},
],
unread: 2,
},
},
};
const newState = reducer(state, action);
expect(Object.keys(newState.linkmans['1'].messages).length).toBe(2);
expect(Object.keys(newState.linkmans['2'].messages).length).toBe(0);
});
it('should add messages to linkman', () => {
const state = {
linkmans: {
1: {
_id: '1',
name: 'name',
messages: {},
},
},
} as unknown as State;
const action = {
type: ActionTypes.AddLinkmanHistoryMessages,
payload: {
linkmanId: '1',
messages: [
{
_id: 'm1',
type: 'text',
content: 'content',
},
{
_id: 'm2',
type: 'text',
content: 'content',
},
],
},
};
const newState = reducer(state, action);
expect(Object.keys(newState.linkmans['1'].messages).length).toBe(2);
});
it('should add message to linkman', () => {
const linkman = {
_id: '1',
name: 'name',
messages: {},
unread: 0,
};
const state = {
linkmans: {
[linkman._id]: linkman,
},
} as State;
const action = {
type: ActionTypes.AddLinkmanMessage,
payload: {
linkmanId: '1',
message: {
_id: 'm1',
type: 'text',
content: 'content',
},
},
};
const newState = reducer(state, action);
expect(Object.keys(newState.linkmans['1'].messages)).toHaveLength(1);
expect(newState.linkmans['1'].unread).toBe(1);
});
it('should not increase unread count when linkman is foucs', () => {
const linkman = {
_id: '1',
name: 'name',
messages: {},
unread: 0,
};
const state = {
linkmans: {
[linkman._id]: linkman,
},
focus: linkman._id,
} as State;
const action = {
type: ActionTypes.AddLinkmanMessage,
payload: {
linkmanId: '1',
message: {
_id: 'm1',
type: 'text',
content: 'content',
},
},
};
const newState = reducer(state, action);
expect(Object.keys(newState.linkmans['1'].messages)).toHaveLength(1);
expect(newState.linkmans['1'].unread).toBe(0);
});
it('should remove message from linkman', () => {
const state = {
linkmans: {
1: {
_id: '1',
name: 'name',
messages: {
m1: {
_id: 'm1',
type: 'text',
content: 'content',
from: {},
},
},
unread: 0,
},
},
} as unknown as State;
const action = {
type: ActionTypes.DeleteMessage,
payload: {
linkmanId: '1',
messageId: 'm1',
},
};
const newState = reducer(state, action);
expect(newState.linkmans['1'].messages.m1.deleted).toBe(true);
});
it('should return origin state when delete not exists linkman message', () => {
const state = {
linkmans: {},
} as State;
const action = {
type: ActionTypes.DeleteMessage,
payload: {
linkmanId: '1',
messageId: 'm1',
},
};
const newState = reducer(state, action);
expect(newState).toBe(state);
});
it('should update linkman property', () => {
const state = {
linkmans: {
1: {
_id: '1',
name: 'name',
messages: {},
unread: 0,
},
},
} as unknown as State;
const action = {
type: ActionTypes.SetLinkmanProperty,
payload: {
linkmanId: '1',
key: 'name',
value: 'new_name',
},
};
const newState = reducer(state, action);
expect(newState.linkmans['1'].name).toBe('new_name');
});
it('should update message from linkman', () => {
const state = {
linkmans: {
1: {
_id: '1',
name: 'name',
messages: {
m1: {
_id: 'm1',
type: 'text',
content: 'content',
},
},
unread: 0,
},
},
} as unknown as State;
const action = {
type: ActionTypes.UpdateMessage,
payload: {
linkmanId: '1',
messageId: 'm1',
value: {
_id: 'm1',
type: 'text',
content: 'new_content',
},
},
};
const newState = reducer(state, action);
expect(newState.linkmans['1'].messages.m1.content).toBe('new_content');
});
it('should add instead of update message when it not exists', () => {
const linkman = {
_id: '1',
name: 'name',
messages: {},
unread: 0,
};
const state = {
linkmans: {
[linkman._id]: linkman,
},
} as State;
const action = {
type: ActionTypes.UpdateMessage,
payload: {
linkmanId: linkman._id,
messageId: 'm1',
value: {
type: 'text',
content: 'new_content',
},
},
};
const newState = reducer(state, action);
expect(newState.linkmans[linkman._id].messages.m1.content).toBe(
'new_content',
);
});
it('should update status of key', () => {
const state = {
status: {
aero: false,
},
} as unknown as State;
const action = {
type: ActionTypes.SetStatus,
payload: {
key: 'aero',
value: true,
},
};
const newState = reducer(state, action);
expect(newState.status.aero).toBe(true);
});
});