Fixes story play order
This commit is contained in:
parent
4308739bc0
commit
0be580e8e5
4 changed files with 471 additions and 30 deletions
|
@ -40,7 +40,10 @@ import {
|
||||||
isDownloaded,
|
isDownloaded,
|
||||||
isDownloading,
|
isDownloading,
|
||||||
} from '../../types/Attachment';
|
} from '../../types/Attachment';
|
||||||
import { getConversationSelector } from '../selectors/conversations';
|
import {
|
||||||
|
getConversationSelector,
|
||||||
|
getHideStoryConversationIds,
|
||||||
|
} from '../selectors/conversations';
|
||||||
import { getSendOptions } from '../../util/getSendOptions';
|
import { getSendOptions } from '../../util/getSendOptions';
|
||||||
import { getStories } from '../selectors/stories';
|
import { getStories } from '../selectors/stories';
|
||||||
import { getStoryDataFromMessageAttributes } from '../../services/storyLoader';
|
import { getStoryDataFromMessageAttributes } from '../../services/storyLoader';
|
||||||
|
@ -826,19 +829,25 @@ const viewUserStories: ViewUserStoriesActionCreatorType = ({
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type ViewStoryOptionsType =
|
||||||
|
| {
|
||||||
|
closeViewer: true;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
storyId: string;
|
||||||
|
storyViewMode: StoryViewModeType;
|
||||||
|
viewDirection?: StoryViewDirectionType;
|
||||||
|
shouldShowDetailsModal?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
export type ViewStoryActionCreatorType = (
|
export type ViewStoryActionCreatorType = (
|
||||||
opts:
|
opts: ViewStoryOptionsType
|
||||||
| {
|
|
||||||
closeViewer: true;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
storyId: string;
|
|
||||||
storyViewMode: StoryViewModeType;
|
|
||||||
viewDirection?: StoryViewDirectionType;
|
|
||||||
shouldShowDetailsModal?: boolean;
|
|
||||||
}
|
|
||||||
) => unknown;
|
) => unknown;
|
||||||
|
|
||||||
|
export type DispatchableViewStoryType = (
|
||||||
|
opts: ViewStoryOptionsType
|
||||||
|
) => ThunkAction<void, RootStateType, unknown, ViewStoryActionType>;
|
||||||
|
|
||||||
const viewStory: ViewStoryActionCreatorType = (
|
const viewStory: ViewStoryActionCreatorType = (
|
||||||
opts
|
opts
|
||||||
): ThunkAction<void, RootStateType, unknown, ViewStoryActionType> => {
|
): ThunkAction<void, RootStateType, unknown, ViewStoryActionType> => {
|
||||||
|
@ -954,10 +963,20 @@ const viewStory: ViewStoryActionCreatorType = (
|
||||||
// Are there any unviewed stories left? If so we should play the unviewed
|
// Are there any unviewed stories left? If so we should play the unviewed
|
||||||
// stories first. But only if we're going "next"
|
// stories first. But only if we're going "next"
|
||||||
if (viewDirection === StoryViewDirectionType.Next) {
|
if (viewDirection === StoryViewDirectionType.Next) {
|
||||||
const unreadStory = stories.find(
|
// Only stories that succeed the current story we're on.
|
||||||
item =>
|
const currentStoryIndex = stories.findIndex(
|
||||||
item.readStatus === ReadStatus.Unread && !item.deletedForEveryone
|
item => item.messageId === storyId
|
||||||
);
|
);
|
||||||
|
// No hidden stories
|
||||||
|
const hiddenConversationIds = new Set(getHideStoryConversationIds(state));
|
||||||
|
const unreadStory = stories.find(
|
||||||
|
(item, index) =>
|
||||||
|
index > currentStoryIndex &&
|
||||||
|
!item.deletedForEveryone &&
|
||||||
|
item.readStatus === ReadStatus.Unread &&
|
||||||
|
!hiddenConversationIds.has(item.conversationId)
|
||||||
|
);
|
||||||
|
|
||||||
if (unreadStory) {
|
if (unreadStory) {
|
||||||
const nextSelectedStoryData = getSelectedStoryDataForConversationId(
|
const nextSelectedStoryData = getSelectedStoryDataForConversationId(
|
||||||
dispatch,
|
dispatch,
|
||||||
|
@ -977,6 +996,16 @@ const viewStory: ViewStoryActionCreatorType = (
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Close the viewer if we were viewing unread stories only and we did not
|
||||||
|
// find any more unread.
|
||||||
|
if (storyViewMode === StoryViewModeType.Unread) {
|
||||||
|
dispatch({
|
||||||
|
type: VIEW_STORY,
|
||||||
|
payload: undefined,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const conversationStories = getStories(state).stories;
|
const conversationStories = getStories(state).stories;
|
||||||
|
@ -1018,19 +1047,6 @@ const viewStory: ViewStoryActionCreatorType = (
|
||||||
conversationStory.conversationId
|
conversationStory.conversationId
|
||||||
);
|
);
|
||||||
|
|
||||||
// Close the viewer if we were viewing unread stories only and we've
|
|
||||||
// reached the last unread story.
|
|
||||||
if (
|
|
||||||
!nextSelectedStoryData.hasUnread &&
|
|
||||||
storyViewMode === StoryViewModeType.Unread
|
|
||||||
) {
|
|
||||||
dispatch({
|
|
||||||
type: VIEW_STORY,
|
|
||||||
payload: undefined,
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: VIEW_STORY,
|
type: VIEW_STORY,
|
||||||
payload: {
|
payload: {
|
||||||
|
|
|
@ -1050,3 +1050,11 @@ export const getConversationsStoppingSend = createSelector(
|
||||||
return sortByTitle(conversations);
|
return sortByTitle(conversations);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const getHideStoryConversationIds = createSelector(
|
||||||
|
getConversationLookup,
|
||||||
|
(conversationLookup): Array<string> =>
|
||||||
|
Object.keys(conversationLookup).filter(
|
||||||
|
conversationId => conversationLookup[conversationId].hideStory
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
|
@ -27,6 +27,7 @@ import { canReply } from './message';
|
||||||
import {
|
import {
|
||||||
getContactNameColorSelector,
|
getContactNameColorSelector,
|
||||||
getConversationSelector,
|
getConversationSelector,
|
||||||
|
getHideStoryConversationIds,
|
||||||
getMe,
|
getMe,
|
||||||
} from './conversations';
|
} from './conversations';
|
||||||
import { getUserConversationId } from './user';
|
import { getUserConversationId } from './user';
|
||||||
|
@ -412,15 +413,19 @@ export const getStories = createSelector(
|
||||||
);
|
);
|
||||||
|
|
||||||
export const getStoriesNotificationCount = createSelector(
|
export const getStoriesNotificationCount = createSelector(
|
||||||
|
getHideStoryConversationIds,
|
||||||
getStoriesState,
|
getStoriesState,
|
||||||
({ lastOpenedAtTimestamp, stories }): number => {
|
(hideStoryConversationIds, { lastOpenedAtTimestamp, stories }): number => {
|
||||||
|
const hiddenConversationIds = new Set(hideStoryConversationIds);
|
||||||
|
|
||||||
return new Set(
|
return new Set(
|
||||||
stories
|
stories
|
||||||
.filter(
|
.filter(
|
||||||
story =>
|
story =>
|
||||||
story.readStatus === ReadStatus.Unread &&
|
story.readStatus === ReadStatus.Unread &&
|
||||||
!story.deletedForEveryone &&
|
!story.deletedForEveryone &&
|
||||||
story.timestamp > (lastOpenedAtTimestamp || 0)
|
story.timestamp > (lastOpenedAtTimestamp || 0) &&
|
||||||
|
!hiddenConversationIds.has(story.conversationId)
|
||||||
)
|
)
|
||||||
.map(story => story.conversationId)
|
.map(story => story.conversationId)
|
||||||
).size;
|
).size;
|
||||||
|
|
|
@ -2,13 +2,26 @@
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import * as sinon from 'sinon';
|
import * as sinon from 'sinon';
|
||||||
|
import casual from 'casual';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { assert } from 'chai';
|
import { assert } from 'chai';
|
||||||
import { v4 as uuid } from 'uuid';
|
import { v4 as uuid } from 'uuid';
|
||||||
|
|
||||||
import type { StoriesStateType } from '../../../state/ducks/stories';
|
import type {
|
||||||
|
DispatchableViewStoryType,
|
||||||
|
StoriesStateType,
|
||||||
|
StoryDataType,
|
||||||
|
} from '../../../state/ducks/stories';
|
||||||
|
import type { ConversationType } from '../../../state/ducks/conversations';
|
||||||
import type { MessageAttributesType } from '../../../model-types.d';
|
import type { MessageAttributesType } from '../../../model-types.d';
|
||||||
|
import type { StateType as RootStateType } from '../../../state/reducer';
|
||||||
|
import { DAY } from '../../../util/durations';
|
||||||
import { IMAGE_JPEG } from '../../../types/MIME';
|
import { IMAGE_JPEG } from '../../../types/MIME';
|
||||||
|
import { ReadStatus } from '../../../messages/MessageReadStatus';
|
||||||
|
import {
|
||||||
|
StoryViewDirectionType,
|
||||||
|
StoryViewModeType,
|
||||||
|
} from '../../../types/Stories';
|
||||||
import {
|
import {
|
||||||
actions,
|
actions,
|
||||||
getEmptyState,
|
getEmptyState,
|
||||||
|
@ -38,6 +51,405 @@ describe('both/state/ducks/stories', () => {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
describe('viewStory', () => {
|
||||||
|
function getMockConversation({
|
||||||
|
id: conversationId,
|
||||||
|
hideStory = false,
|
||||||
|
}: Pick<ConversationType, 'id' | 'hideStory'>): ConversationType {
|
||||||
|
return {
|
||||||
|
acceptedMessageRequest: true,
|
||||||
|
badges: [],
|
||||||
|
hideStory,
|
||||||
|
id: conversationId,
|
||||||
|
isMe: false,
|
||||||
|
sharedGroupNames: [],
|
||||||
|
title: casual.username,
|
||||||
|
type: 'direct' as const,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getStoryData(
|
||||||
|
messageId: string,
|
||||||
|
conversationId = uuid()
|
||||||
|
): StoryDataType {
|
||||||
|
const now = Date.now();
|
||||||
|
|
||||||
|
return {
|
||||||
|
conversationId,
|
||||||
|
expirationStartTimestamp: now,
|
||||||
|
expireTimer: 1 * DAY,
|
||||||
|
messageId,
|
||||||
|
readStatus: ReadStatus.Unread,
|
||||||
|
timestamp: now,
|
||||||
|
type: 'story',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getStateFunction(
|
||||||
|
stories: Array<StoryDataType>,
|
||||||
|
conversationLookup: { [key: string]: ConversationType } = {}
|
||||||
|
): () => RootStateType {
|
||||||
|
const rootState = getEmptyRootState();
|
||||||
|
|
||||||
|
return () => ({
|
||||||
|
...rootState,
|
||||||
|
conversations: {
|
||||||
|
...rootState.conversations,
|
||||||
|
conversationLookup,
|
||||||
|
},
|
||||||
|
stories: {
|
||||||
|
...rootState.stories,
|
||||||
|
stories,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const viewStory = actions.viewStory as DispatchableViewStoryType;
|
||||||
|
|
||||||
|
it('closes the viewer', () => {
|
||||||
|
const dispatch = sinon.spy();
|
||||||
|
|
||||||
|
viewStory({ closeViewer: true })(dispatch, getEmptyRootState, null);
|
||||||
|
|
||||||
|
sinon.assert.calledWith(dispatch, {
|
||||||
|
type: 'stories/VIEW_STORY',
|
||||||
|
payload: undefined,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not find a story', () => {
|
||||||
|
const dispatch = sinon.spy();
|
||||||
|
viewStory({
|
||||||
|
storyId: uuid(),
|
||||||
|
storyViewMode: StoryViewModeType.All,
|
||||||
|
})(dispatch, getEmptyRootState, null);
|
||||||
|
|
||||||
|
sinon.assert.calledWith(dispatch, {
|
||||||
|
type: 'stories/VIEW_STORY',
|
||||||
|
payload: undefined,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('selects a specific story', () => {
|
||||||
|
const storyId = uuid();
|
||||||
|
|
||||||
|
const getState = getStateFunction([getStoryData(storyId)]);
|
||||||
|
|
||||||
|
const dispatch = sinon.spy();
|
||||||
|
viewStory({
|
||||||
|
storyId,
|
||||||
|
storyViewMode: StoryViewModeType.All,
|
||||||
|
})(dispatch, getState, null);
|
||||||
|
|
||||||
|
sinon.assert.calledWith(dispatch, {
|
||||||
|
type: 'stories/VIEW_STORY',
|
||||||
|
payload: {
|
||||||
|
currentIndex: 0,
|
||||||
|
messageId: storyId,
|
||||||
|
numStories: 1,
|
||||||
|
shouldShowDetailsModal: false,
|
||||||
|
storyViewMode: StoryViewModeType.All,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("navigating within a user's stories", () => {
|
||||||
|
it('selects the next story', () => {
|
||||||
|
const storyId1 = uuid();
|
||||||
|
const storyId2 = uuid();
|
||||||
|
const storyId3 = uuid();
|
||||||
|
const conversationId = uuid();
|
||||||
|
const getState = getStateFunction([
|
||||||
|
getStoryData(storyId1, conversationId),
|
||||||
|
getStoryData(storyId2, conversationId),
|
||||||
|
getStoryData(storyId3, conversationId),
|
||||||
|
]);
|
||||||
|
|
||||||
|
const dispatch = sinon.spy();
|
||||||
|
viewStory({
|
||||||
|
storyId: storyId1,
|
||||||
|
storyViewMode: StoryViewModeType.User,
|
||||||
|
viewDirection: StoryViewDirectionType.Next,
|
||||||
|
})(dispatch, getState, null);
|
||||||
|
|
||||||
|
sinon.assert.calledWith(dispatch, {
|
||||||
|
type: 'stories/VIEW_STORY',
|
||||||
|
payload: {
|
||||||
|
currentIndex: 1,
|
||||||
|
messageId: storyId2,
|
||||||
|
numStories: 3,
|
||||||
|
shouldShowDetailsModal: false,
|
||||||
|
storyViewMode: StoryViewModeType.User,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('selects the prev story', () => {
|
||||||
|
const storyId1 = uuid();
|
||||||
|
const storyId2 = uuid();
|
||||||
|
const storyId3 = uuid();
|
||||||
|
const conversationId = uuid();
|
||||||
|
const getState = getStateFunction([
|
||||||
|
getStoryData(storyId1, conversationId),
|
||||||
|
getStoryData(storyId2, conversationId),
|
||||||
|
getStoryData(storyId3, conversationId),
|
||||||
|
]);
|
||||||
|
|
||||||
|
const dispatch = sinon.spy();
|
||||||
|
viewStory({
|
||||||
|
storyId: storyId2,
|
||||||
|
storyViewMode: StoryViewModeType.User,
|
||||||
|
viewDirection: StoryViewDirectionType.Previous,
|
||||||
|
})(dispatch, getState, null);
|
||||||
|
|
||||||
|
sinon.assert.calledWith(dispatch, {
|
||||||
|
type: 'stories/VIEW_STORY',
|
||||||
|
payload: {
|
||||||
|
currentIndex: 0,
|
||||||
|
messageId: storyId1,
|
||||||
|
numStories: 3,
|
||||||
|
shouldShowDetailsModal: false,
|
||||||
|
storyViewMode: StoryViewModeType.User,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('when in StoryViewModeType.User and we have reached the end, it closes the viewer', () => {
|
||||||
|
const storyId1 = uuid();
|
||||||
|
const storyId2 = uuid();
|
||||||
|
const storyId3 = uuid();
|
||||||
|
const conversationId = uuid();
|
||||||
|
const getState = getStateFunction([
|
||||||
|
getStoryData(storyId1, conversationId),
|
||||||
|
getStoryData(storyId2, conversationId),
|
||||||
|
getStoryData(storyId3, conversationId),
|
||||||
|
]);
|
||||||
|
|
||||||
|
const dispatch = sinon.spy();
|
||||||
|
viewStory({
|
||||||
|
storyId: storyId3,
|
||||||
|
storyViewMode: StoryViewModeType.User,
|
||||||
|
viewDirection: StoryViewDirectionType.Next,
|
||||||
|
})(dispatch, getState, null);
|
||||||
|
|
||||||
|
sinon.assert.calledWith(dispatch, {
|
||||||
|
type: 'stories/VIEW_STORY',
|
||||||
|
payload: undefined,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('unviewed stories', () => {
|
||||||
|
it('finds any unviewed stories and selects them', () => {
|
||||||
|
const storyId1 = uuid();
|
||||||
|
const storyId2 = uuid();
|
||||||
|
const storyId3 = uuid();
|
||||||
|
const getState = getStateFunction([
|
||||||
|
getStoryData(storyId1),
|
||||||
|
{
|
||||||
|
...getStoryData(storyId2),
|
||||||
|
readStatus: ReadStatus.Viewed,
|
||||||
|
},
|
||||||
|
getStoryData(storyId3),
|
||||||
|
]);
|
||||||
|
|
||||||
|
const dispatch = sinon.spy();
|
||||||
|
viewStory({
|
||||||
|
storyId: storyId1,
|
||||||
|
storyViewMode: StoryViewModeType.Unread,
|
||||||
|
viewDirection: StoryViewDirectionType.Next,
|
||||||
|
})(dispatch, getState, null);
|
||||||
|
|
||||||
|
sinon.assert.calledWith(dispatch, {
|
||||||
|
type: 'stories/VIEW_STORY',
|
||||||
|
payload: {
|
||||||
|
currentIndex: 0,
|
||||||
|
messageId: storyId3,
|
||||||
|
numStories: 1,
|
||||||
|
shouldShowDetailsModal: false,
|
||||||
|
storyViewMode: StoryViewModeType.Unread,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not select hidden stories', () => {
|
||||||
|
const storyId1 = uuid();
|
||||||
|
const storyId2 = uuid();
|
||||||
|
const storyId3 = uuid();
|
||||||
|
const conversationId = uuid();
|
||||||
|
|
||||||
|
const getState = getStateFunction(
|
||||||
|
[
|
||||||
|
getStoryData(storyId1),
|
||||||
|
getStoryData(storyId2, conversationId),
|
||||||
|
getStoryData(storyId3, conversationId),
|
||||||
|
],
|
||||||
|
{
|
||||||
|
[conversationId]: getMockConversation({
|
||||||
|
id: conversationId,
|
||||||
|
hideStory: true,
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const dispatch = sinon.spy();
|
||||||
|
viewStory({
|
||||||
|
storyId: storyId1,
|
||||||
|
storyViewMode: StoryViewModeType.Unread,
|
||||||
|
viewDirection: StoryViewDirectionType.Next,
|
||||||
|
})(dispatch, getState, null);
|
||||||
|
|
||||||
|
sinon.assert.calledWith(dispatch, {
|
||||||
|
type: 'stories/VIEW_STORY',
|
||||||
|
payload: undefined,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not select stories that precede the currently viewed story', () => {
|
||||||
|
const storyId1 = uuid();
|
||||||
|
const storyId2 = uuid();
|
||||||
|
const storyId3 = uuid();
|
||||||
|
const getState = getStateFunction([
|
||||||
|
getStoryData(storyId1),
|
||||||
|
getStoryData(storyId2),
|
||||||
|
getStoryData(storyId3),
|
||||||
|
]);
|
||||||
|
|
||||||
|
const dispatch = sinon.spy();
|
||||||
|
viewStory({
|
||||||
|
storyId: storyId3,
|
||||||
|
storyViewMode: StoryViewModeType.Unread,
|
||||||
|
viewDirection: StoryViewDirectionType.Next,
|
||||||
|
})(dispatch, getState, null);
|
||||||
|
|
||||||
|
sinon.assert.calledWith(dispatch, {
|
||||||
|
type: 'stories/VIEW_STORY',
|
||||||
|
payload: undefined,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('closes the viewer when there are no more unviewed stories', () => {
|
||||||
|
const storyId1 = uuid();
|
||||||
|
const storyId2 = uuid();
|
||||||
|
|
||||||
|
const conversationId1 = uuid();
|
||||||
|
const conversationId2 = uuid();
|
||||||
|
|
||||||
|
const getState = getStateFunction(
|
||||||
|
[
|
||||||
|
getStoryData(storyId1, conversationId1),
|
||||||
|
{
|
||||||
|
...getStoryData(storyId2, conversationId2),
|
||||||
|
readStatus: ReadStatus.Viewed,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
{
|
||||||
|
[conversationId1]: getMockConversation({ id: conversationId1 }),
|
||||||
|
[conversationId2]: getMockConversation({ id: conversationId2 }),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const dispatch = sinon.spy();
|
||||||
|
viewStory({
|
||||||
|
storyId: storyId1,
|
||||||
|
storyViewMode: StoryViewModeType.Unread,
|
||||||
|
viewDirection: StoryViewDirectionType.Next,
|
||||||
|
})(dispatch, getState, null);
|
||||||
|
|
||||||
|
sinon.assert.calledWith(dispatch, {
|
||||||
|
type: 'stories/VIEW_STORY',
|
||||||
|
payload: undefined,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('paging through collections of stories', () => {
|
||||||
|
function getViewedStoryData(
|
||||||
|
storyId: string,
|
||||||
|
conversationId?: string
|
||||||
|
): StoryDataType {
|
||||||
|
return {
|
||||||
|
...getStoryData(storyId, conversationId),
|
||||||
|
readStatus: ReadStatus.Viewed,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
it("goes to the next user's stories", () => {
|
||||||
|
const storyId1 = uuid();
|
||||||
|
const storyId2 = uuid();
|
||||||
|
const storyId3 = uuid();
|
||||||
|
const conversationId2 = uuid();
|
||||||
|
const conversationId1 = uuid();
|
||||||
|
const getState = getStateFunction(
|
||||||
|
[
|
||||||
|
getViewedStoryData(storyId1, conversationId1),
|
||||||
|
getViewedStoryData(storyId2, conversationId2),
|
||||||
|
getViewedStoryData(storyId3, conversationId2),
|
||||||
|
],
|
||||||
|
{
|
||||||
|
[conversationId1]: getMockConversation({ id: conversationId1 }),
|
||||||
|
[conversationId2]: getMockConversation({ id: conversationId2 }),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const dispatch = sinon.spy();
|
||||||
|
viewStory({
|
||||||
|
storyId: storyId1,
|
||||||
|
storyViewMode: StoryViewModeType.All,
|
||||||
|
viewDirection: StoryViewDirectionType.Next,
|
||||||
|
})(dispatch, getState, null);
|
||||||
|
|
||||||
|
sinon.assert.calledWith(dispatch, {
|
||||||
|
type: 'stories/VIEW_STORY',
|
||||||
|
payload: {
|
||||||
|
currentIndex: 0,
|
||||||
|
messageId: storyId2,
|
||||||
|
numStories: 2,
|
||||||
|
shouldShowDetailsModal: false,
|
||||||
|
storyViewMode: StoryViewModeType.All,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("goes to the prev user's stories", () => {
|
||||||
|
const storyId1 = uuid();
|
||||||
|
const storyId2 = uuid();
|
||||||
|
const storyId3 = uuid();
|
||||||
|
const conversationId1 = uuid();
|
||||||
|
const conversationId2 = uuid();
|
||||||
|
const getState = getStateFunction(
|
||||||
|
[
|
||||||
|
getViewedStoryData(storyId1, conversationId2),
|
||||||
|
getViewedStoryData(storyId2, conversationId1),
|
||||||
|
getViewedStoryData(storyId3, conversationId2),
|
||||||
|
],
|
||||||
|
{
|
||||||
|
[conversationId1]: getMockConversation({ id: conversationId1 }),
|
||||||
|
[conversationId2]: getMockConversation({ id: conversationId2 }),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const dispatch = sinon.spy();
|
||||||
|
viewStory({
|
||||||
|
storyId: storyId2,
|
||||||
|
storyViewMode: StoryViewModeType.All,
|
||||||
|
viewDirection: StoryViewDirectionType.Previous,
|
||||||
|
})(dispatch, getState, null);
|
||||||
|
|
||||||
|
sinon.assert.calledWith(dispatch, {
|
||||||
|
type: 'stories/VIEW_STORY',
|
||||||
|
payload: {
|
||||||
|
currentIndex: 0,
|
||||||
|
messageId: storyId1,
|
||||||
|
numStories: 2,
|
||||||
|
shouldShowDetailsModal: false,
|
||||||
|
storyViewMode: StoryViewModeType.All,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('queueStoryDownload', () => {
|
describe('queueStoryDownload', () => {
|
||||||
const { queueStoryDownload } = actions;
|
const { queueStoryDownload } = actions;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue