How to use CHANNEL1 method in wpt

Best JavaScript code snippet using wpt

posts.test.js

Source:posts.test.js Github

copy

Full Screen

1// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.2// See LICENSE.txt for license information.3import assert from 'assert';4import expect from 'expect';5import {6 ChannelTypes,7 GeneralTypes,8 PostTypes,9} from 'action_types';10import {Posts} from '../../constants';11import * as reducers from 'reducers/entities/posts';12import deepFreeze from 'utils/deep_freeze';13describe('posts', () => {14 for (const actionType of [15 PostTypes.RECEIVED_POST,16 PostTypes.RECEIVED_NEW_POST,17 ]) {18 describe(`received a single post (${actionType})`, () => {19 it('should add a new post', () => {20 const state = deepFreeze({21 post1: {id: 'post1'},22 });23 const nextState = reducers.handlePosts(state, {24 type: actionType,25 data: {id: 'post2'},26 });27 expect(nextState).not.toBe(state);28 expect(nextState.post1).toBe(state.post1);29 expect(nextState).toEqual({30 post1: {id: 'post1'},31 post2: {id: 'post2'},32 });33 });34 it('should add a new pending post', () => {35 const state = deepFreeze({36 post1: {id: 'post1'},37 });38 const nextState = reducers.handlePosts(state, {39 type: actionType,40 data: {id: 'post2', pending_post_id: 'post2'},41 });42 expect(nextState).not.toBe(state);43 expect(nextState.post1).toBe(state.post1);44 expect(nextState).toEqual({45 post1: {id: 'post1'},46 post2: {id: 'post2', pending_post_id: 'post2'},47 });48 });49 it('should update an existing post', () => {50 const state = deepFreeze({51 post1: {id: 'post1', message: '123'},52 });53 const nextState = reducers.handlePosts(state, {54 type: actionType,55 data: {id: 'post1', message: 'abc'},56 });57 expect(nextState).not.toBe(state);58 expect(nextState.post1).not.toBe(state.post1);59 expect(nextState).toEqual({60 post1: {id: 'post1', message: 'abc'},61 });62 });63 it('should remove any pending posts when receiving the actual post', () => {64 const state = deepFreeze({65 pending: {id: 'pending'},66 });67 const nextState = reducers.handlePosts(state, {68 type: actionType,69 data: {id: 'post1', pending_post_id: 'pending'},70 });71 expect(nextState).not.toBe(state);72 expect(nextState).toEqual({73 post1: {id: 'post1', pending_post_id: 'pending'},74 });75 });76 });77 }78 describe('received multiple posts', () => {79 it('should do nothing when post list is empty', () => {80 const state = deepFreeze({81 post1: {id: 'post1'},82 });83 const nextState = reducers.handlePosts(state, {84 type: PostTypes.RECEIVED_POSTS,85 data: {86 order: [],87 posts: {},88 },89 });90 expect(nextState).toBe(state);91 });92 it('should add new posts', () => {93 const state = deepFreeze({94 post1: {id: 'post1'},95 });96 const nextState = reducers.handlePosts(state, {97 type: PostTypes.RECEIVED_POSTS,98 data: {99 order: ['post2', 'post3'],100 posts: {101 post2: {id: 'post2'},102 post3: {id: 'post3'},103 },104 },105 });106 expect(nextState).not.toBe(state);107 expect(nextState.post1).toBe(state.post1);108 expect(nextState).toEqual({109 post1: {id: 'post1'},110 post2: {id: 'post2'},111 post3: {id: 'post3'},112 });113 });114 it('should update existing posts unless we have a more recent version', () => {115 const state = deepFreeze({116 post1: {id: 'post1', message: '123', update_at: 1000},117 post2: {id: 'post2', message: '456', update_at: 1000},118 });119 const nextState = reducers.handlePosts(state, {120 type: PostTypes.RECEIVED_POSTS,121 data: {122 order: ['post1', 'post2'],123 posts: {124 post1: {id: 'post1', message: 'abc', update_at: 2000},125 post2: {id: 'post2', message: 'def', update_at: 500},126 },127 },128 });129 expect(nextState).not.toBe(state);130 expect(nextState.post1).not.toBe(state.post1);131 expect(nextState.post2).toBe(state.post2);132 expect(nextState).toEqual({133 post1: {id: 'post1', message: 'abc', update_at: 2000},134 post2: {id: 'post2', message: '456', update_at: 1000},135 });136 });137 it('should set state for deleted posts', () => {138 const state = deepFreeze({139 post1: {id: 'post1', message: '123', delete_at: 0, file_ids: ['file']},140 post2: {id: 'post2', message: '456', delete_at: 0, has_reactions: true},141 });142 const nextState = reducers.handlePosts(state, {143 type: PostTypes.RECEIVED_POSTS,144 data: {145 order: ['post1', 'post2'],146 posts: {147 post1: {id: 'post1', message: '123', delete_at: 2000, file_ids: ['file']},148 post2: {id: 'post2', message: '456', delete_at: 500, has_reactions: true},149 },150 },151 });152 expect(nextState).not.toBe(state);153 expect(nextState.post1).not.toBe(state.post1);154 expect(nextState.post2).not.toBe(state.post2);155 expect(nextState).toEqual({156 post1: {id: 'post1', message: '123', delete_at: 2000, file_ids: [], has_reactions: false, state: Posts.POST_DELETED},157 post2: {id: 'post2', message: '456', delete_at: 500, file_ids: [], has_reactions: false, state: Posts.POST_DELETED},158 });159 });160 it('should remove any pending posts when receiving the actual post', () => {161 const state = deepFreeze({162 pending1: {id: 'pending1'},163 pending2: {id: 'pending2'},164 });165 const nextState = reducers.handlePosts(state, {166 type: PostTypes.RECEIVED_POSTS,167 data: {168 order: ['post1', 'post2'],169 posts: {170 post1: {id: 'post1', pending_post_id: 'pending1'},171 post2: {id: 'post2', pending_post_id: 'pending2'},172 },173 },174 });175 expect(nextState).not.toBe(state);176 expect(nextState).toEqual({177 post1: {id: 'post1', pending_post_id: 'pending1'},178 post2: {id: 'post2', pending_post_id: 'pending2'},179 });180 });181 it('should not add channelId entity to postsInChannel if there were no posts in channel and it has receivedNewPosts on action', () => {182 const state = deepFreeze({183 posts: {},184 postsInChannel: {},185 });186 const action = {187 type: PostTypes.RECEIVED_POSTS,188 data: {189 order: ['postId'],190 posts: {191 postId: {192 id: 'postId',193 },194 },195 },196 channelId: 'channelId',197 receivedNewPosts: true,198 };199 const nextState = reducers.handlePosts(state, action);200 assert.deepEqual(nextState.postsInChannel, {});201 });202 });203 describe(`deleting a post (${PostTypes.POST_DELETED})`, () => {204 it('should mark the post as deleted and remove the rest of the thread', () => {205 const state = deepFreeze({206 post1: {id: 'post1', file_ids: ['file'], has_reactions: true},207 comment1: {id: 'comment1', root_id: 'post1'},208 comment2: {id: 'comment2', root_id: 'post1'},209 });210 const nextState = reducers.handlePosts(state, {211 type: PostTypes.POST_DELETED,212 data: {id: 'post1'},213 });214 expect(nextState).not.toBe(state);215 expect(nextState.post1).not.toBe(state.post1);216 expect(nextState).toEqual({217 post1: {id: 'post1', file_ids: [], has_reactions: false, state: Posts.POST_DELETED},218 });219 });220 it('should not remove the rest of the thread when deleting a comment', () => {221 const state = deepFreeze({222 post1: {id: 'post1'},223 comment1: {id: 'comment1', root_id: 'post1'},224 comment2: {id: 'comment2', root_id: 'post1'},225 });226 const nextState = reducers.handlePosts(state, {227 type: PostTypes.POST_DELETED,228 data: {id: 'comment1'},229 });230 expect(nextState).not.toBe(state);231 expect(nextState.post1).toBe(state.post1);232 expect(nextState.comment1).not.toBe(state.comment1);233 expect(nextState.comment2).toBe(state.comment2);234 expect(nextState).toEqual({235 post1: {id: 'post1'},236 comment1: {id: 'comment1', root_id: 'post1', file_ids: [], has_reactions: false, state: Posts.POST_DELETED},237 comment2: {id: 'comment2', root_id: 'post1'},238 });239 });240 it('should do nothing if the post is not loaded', () => {241 const state = deepFreeze({242 post1: {id: 'post1', file_ids: ['file'], has_reactions: true},243 });244 const nextState = reducers.handlePosts(state, {245 type: PostTypes.POST_DELETED,246 data: {id: 'post2'},247 });248 expect(nextState).toBe(state);249 expect(nextState.post1).toBe(state.post1);250 });251 });252 describe(`removing a post (${PostTypes.POST_REMOVED})`, () => {253 it('should remove the post and the rest and the rest of the thread', () => {254 const state = deepFreeze({255 post1: {id: 'post1', file_ids: ['file'], has_reactions: true},256 comment1: {id: 'comment1', root_id: 'post1'},257 comment2: {id: 'comment2', root_id: 'post1'},258 post2: {id: 'post2'},259 });260 const nextState = reducers.handlePosts(state, {261 type: PostTypes.POST_REMOVED,262 data: {id: 'post1'},263 });264 expect(nextState).not.toBe(state);265 expect(nextState.post2).toBe(state.post2);266 expect(nextState).toEqual({267 post2: {id: 'post2'},268 });269 });270 it('should not remove the rest of the thread when removing a comment', () => {271 const state = deepFreeze({272 post1: {id: 'post1'},273 comment1: {id: 'comment1', root_id: 'post1'},274 comment2: {id: 'comment2', root_id: 'post1'},275 post2: {id: 'post2'},276 });277 const nextState = reducers.handlePosts(state, {278 type: PostTypes.POST_REMOVED,279 data: {id: 'comment1'},280 });281 expect(nextState).not.toBe(state);282 expect(nextState.post1).toBe(state.post1);283 expect(nextState.comment1).not.toBe(state.comment1);284 expect(nextState.comment2).toBe(state.comment2);285 expect(nextState).toEqual({286 post1: {id: 'post1'},287 comment2: {id: 'comment2', root_id: 'post1'},288 post2: {id: 'post2'},289 });290 });291 it('should do nothing if the post is not loaded', () => {292 const state = deepFreeze({293 post1: {id: 'post1', file_ids: ['file'], has_reactions: true},294 });295 const nextState = reducers.handlePosts(state, {296 type: PostTypes.POST_REMOVED,297 data: {id: 'post2'},298 });299 expect(nextState).toBe(state);300 expect(nextState.post1).toBe(state.post1);301 });302 });303 for (const actionType of [304 ChannelTypes.RECEIVED_CHANNEL_DELETED,305 ChannelTypes.DELETE_CHANNEL_SUCCESS,306 ChannelTypes.LEAVE_CHANNEL,307 ]) {308 describe(`when a channel is deleted (${actionType})`, () => {309 it('should remove any posts in that channel', () => {310 const state = deepFreeze({311 post1: {id: 'post1', channel_id: 'channel1'},312 post2: {id: 'post2', channel_id: 'channel1'},313 post3: {id: 'post3', channel_id: 'channel2'},314 });315 const nextState = reducers.handlePosts(state, {316 type: actionType,317 data: {318 id: 'channel1',319 viewArchivedChannels: false,320 },321 });322 expect(nextState).not.toBe(state);323 expect(nextState.post3).toBe(state.post3);324 expect(nextState).toEqual({325 post3: {id: 'post3', channel_id: 'channel2'},326 });327 });328 it('should do nothing if no posts in that channel are loaded', () => {329 const state = deepFreeze({330 post1: {id: 'post1', channel_id: 'channel1'},331 post2: {id: 'post2', channel_id: 'channel1'},332 post3: {id: 'post3', channel_id: 'channel2'},333 });334 const nextState = reducers.handlePosts(state, {335 type: actionType,336 data: {337 id: 'channel3',338 viewArchivedChannels: false,339 },340 });341 expect(nextState).toBe(state);342 expect(nextState.post1).toBe(state.post1);343 expect(nextState.post2).toBe(state.post2);344 expect(nextState.post3).toBe(state.post3);345 });346 it('should not remove any posts with viewArchivedChannels enabled', () => {347 const state = deepFreeze({348 post1: {id: 'post1', channel_id: 'channel1'},349 post2: {id: 'post2', channel_id: 'channel1'},350 post3: {id: 'post3', channel_id: 'channel2'},351 });352 const nextState = reducers.handlePosts(state, {353 type: actionType,354 data: {355 id: 'channel1',356 viewArchivedChannels: true,357 },358 });359 expect(nextState).toBe(state);360 expect(nextState.post1).toBe(state.post1);361 expect(nextState.post2).toBe(state.post2);362 expect(nextState.post3).toBe(state.post3);363 });364 });365 }366});367describe('pendingPostIds', () => {368 describe('making a new pending post', () => {369 it('should add new entries for pending posts', () => {370 const state = deepFreeze(['1234']);371 const nextState = reducers.handlePendingPosts(state, {372 type: PostTypes.RECEIVED_NEW_POST,373 data: {374 pending_post_id: 'abcd',375 },376 });377 expect(nextState).not.toBe(state);378 expect(nextState).toEqual(['1234', 'abcd']);379 });380 it('should not add duplicate entries', () => {381 const state = deepFreeze(['1234']);382 const nextState = reducers.handlePendingPosts(state, {383 type: PostTypes.RECEIVED_NEW_POST,384 data: {385 pending_post_id: '1234',386 },387 });388 expect(nextState).toBe(state);389 expect(nextState).toEqual(['1234']);390 });391 it('should do nothing for regular posts', () => {392 const state = deepFreeze(['1234']);393 const nextState = reducers.handlePendingPosts(state, {394 type: PostTypes.RECEIVED_NEW_POST,395 data: {396 id: 'abcd',397 },398 });399 expect(nextState).toBe(state);400 expect(nextState).toEqual(['1234']);401 });402 });403 describe('removing a pending post', () => {404 it('should remove an entry when its post is deleted', () => {405 const state = deepFreeze(['1234', 'abcd']);406 const nextState = reducers.handlePendingPosts(state, {407 type: PostTypes.POST_REMOVED,408 data: {409 id: 'abcd',410 },411 });412 expect(nextState).not.toBe(state);413 expect(nextState).toEqual(['1234']);414 });415 it('should do nothing without an entry for the post', () => {416 const state = deepFreeze(['1234', 'abcd']);417 const nextState = reducers.handlePendingPosts(state, {418 type: PostTypes.POST_REMOVED,419 data: {420 id: 'wxyz',421 },422 });423 expect(nextState).toBe(state);424 expect(nextState).toEqual(['1234', 'abcd']);425 });426 });427 describe('marking a pending post as completed', () => {428 it('should remove an entry when its post is successfully created', () => {429 const state = deepFreeze(['1234', 'abcd']);430 const nextState = reducers.handlePendingPosts(state, {431 type: PostTypes.RECEIVED_POST,432 data: {433 id: 'post',434 pending_post_id: 'abcd',435 },436 });437 expect(nextState).not.toBe(state);438 expect(nextState).toEqual(['1234']);439 });440 it('should do nothing without an entry for the post', () => {441 const state = deepFreeze(['1234', 'abcd']);442 const nextState = reducers.handlePendingPosts(state, {443 type: PostTypes.RECEIVED_POST,444 data: {445 id: 'post',446 pending_post_id: 'wxyz',447 },448 });449 expect(nextState).toBe(state);450 expect(nextState).toEqual(['1234', 'abcd']);451 });452 it('should do nothing when receiving a non-pending post', () => {453 const state = deepFreeze(['1234', 'abcd']);454 const nextState = reducers.handlePendingPosts(state, {455 type: PostTypes.RECEIVED_POST,456 data: {457 id: 'post',458 },459 });460 expect(nextState).toBe(state);461 expect(nextState).toEqual(['1234', 'abcd']);462 });463 });464});465describe('postsInChannel', () => {466 describe('receiving a new post', () => {467 it('should do nothing without posts loaded for the channel', () => {468 const state = deepFreeze({});469 const nextState = reducers.postsInChannel(state, {470 type: PostTypes.RECEIVED_NEW_POST,471 data: {id: 'post1', channel_id: 'channel1'},472 }, {}, {});473 expect(nextState).toBe(state);474 expect(nextState).toEqual({});475 });476 it('should store the new post when the channel is empty', () => {477 const state = deepFreeze({478 channel1: [],479 });480 const nextState = reducers.postsInChannel(state, {481 type: PostTypes.RECEIVED_NEW_POST,482 data: {id: 'post1', channel_id: 'channel1'},483 });484 expect(nextState).not.toBe(state);485 expect(nextState).toEqual({486 channel1: [487 {order: ['post1'], recent: true},488 ],489 });490 });491 it('should store the new post when the channel has recent posts', () => {492 const state = deepFreeze({493 channel1: [494 {order: ['post2', 'post3'], recent: true},495 ],496 });497 const nextState = reducers.postsInChannel(state, {498 type: PostTypes.RECEIVED_NEW_POST,499 data: {id: 'post1', channel_id: 'channel1'},500 });501 expect(nextState).not.toBe(state);502 expect(nextState).toEqual({503 channel1: [504 {order: ['post1', 'post2', 'post3'], recent: true},505 ],506 });507 });508 it('should not store the new post when the channel only has older posts', () => {509 const state = deepFreeze({510 channel1: [511 {order: ['post2', 'post3'], recent: false},512 ],513 });514 const nextState = reducers.postsInChannel(state, {515 type: PostTypes.RECEIVED_NEW_POST,516 data: {id: 'post1', channel_id: 'channel1'},517 });518 expect(nextState).toEqual({519 channel1: [520 {order: ['post2', 'post3'], recent: false}, {order: ['post1'], recent: true},521 ],522 });523 });524 it('should do nothing for a duplicate post', () => {525 const state = deepFreeze({526 channel1: [527 {order: ['post1', 'post2', 'post3'], recent: true},528 ],529 });530 const nextState = reducers.postsInChannel(state, {531 type: PostTypes.RECEIVED_NEW_POST,532 data: {id: 'post1', channel_id: 'channel1'},533 });534 expect(nextState).toBe(state);535 });536 it('should remove a previously pending post', () => {537 const state = deepFreeze({538 channel1: [539 {order: ['pending', 'post2', 'post1'], recent: true},540 ],541 });542 const nextState = reducers.postsInChannel(state, {543 type: PostTypes.RECEIVED_NEW_POST,544 data: {id: 'post3', channel_id: 'channel1', pending_post_id: 'pending'},545 }, {}, {post1: {create_at: 1}, post2: {create_at: 2}, post3: {create_at: 3}});546 expect(nextState).not.toBe(state);547 expect(nextState).toEqual({548 channel1: [549 {order: ['post3', 'post2', 'post1'], recent: true},550 ],551 });552 });553 it('should just add the new post if the pending post was already removed', () => {554 const state = deepFreeze({555 channel1: [556 {order: ['post1', 'post2'], recent: true},557 ],558 });559 const nextState = reducers.postsInChannel(state, {560 type: PostTypes.RECEIVED_NEW_POST,561 data: {id: 'post3', channel_id: 'channel1', pending_post_id: 'pending'},562 });563 expect(nextState).not.toBe(state);564 expect(nextState).toEqual({565 channel1: [566 {order: ['post3', 'post1', 'post2'], recent: true},567 ],568 });569 });570 it('should not include a previously removed post', () => {571 const state = deepFreeze({572 channel1: [573 {order: ['post1'], recent: true},574 ],575 });576 const nextState = reducers.postsInChannel(state, {577 type: PostTypes.POST_REMOVED,578 data: {id: 'post1', channel_id: 'channel1'},579 });580 expect(nextState).not.toBe(state);581 expect(nextState).toEqual({582 channel1: [{583 order: [],584 recent: true,585 }],586 });587 });588 });589 describe('receiving a single post', () => {590 it('should replace a previously pending post', () => {591 const state = deepFreeze({592 channel1: [593 {order: ['post1', 'pending', 'post2'], recent: true},594 ],595 });596 const nextState = reducers.postsInChannel(state, {597 type: PostTypes.RECEIVED_POST,598 data: {id: 'post3', channel_id: 'channel1', pending_post_id: 'pending'},599 });600 expect(nextState).not.toBe(state);601 expect(nextState).toEqual({602 channel1: [603 {order: ['post1', 'post3', 'post2'], recent: true},604 ],605 });606 });607 it('should do nothing for a pending post that was already removed', () => {608 const state = deepFreeze({609 channel1: [610 {order: ['post1', 'post2'], recent: true},611 ],612 });613 const nextState = reducers.postsInChannel(state, {614 type: PostTypes.RECEIVED_POST,615 data: {id: 'post3', channel_id: 'channel1', pending_post_id: 'pending'},616 });617 expect(nextState).toBe(state);618 expect(nextState).toEqual({619 channel1: [620 {order: ['post1', 'post2'], recent: true},621 ],622 });623 });624 it('should do nothing for a post that was not previously pending', () => {625 const state = deepFreeze({626 channel1: [627 {order: ['post1', 'pending', 'post2'], recent: true},628 ],629 });630 const nextState = reducers.postsInChannel(state, {631 type: PostTypes.RECEIVED_POST,632 data: {id: 'post3', channel_id: 'channel1'},633 });634 expect(nextState).toBe(state);635 expect(nextState).toEqual({636 channel1: [637 {order: ['post1', 'pending', 'post2'], recent: true},638 ],639 });640 });641 it('should do nothing for a post without posts loaded for the channel', () => {642 const state = deepFreeze({643 channel1: [644 {order: ['post1', 'post2'], recent: true},645 ],646 });647 const nextState = reducers.postsInChannel(state, {648 type: PostTypes.RECEIVED_POST,649 data: {id: 'post3', channel_id: 'channel2', pending_post_id: 'pending'},650 });651 expect(nextState).toBe(state);652 expect(nextState).toEqual({653 channel1: [654 {order: ['post1', 'post2'], recent: true},655 ],656 });657 });658 });659 describe('receiving consecutive recent posts in the channel', () => {660 it('should save posts in the correct order', () => {661 const state = deepFreeze({662 channel1: [663 {order: ['post2', 'post4'], recent: true},664 ],665 });666 const nextPosts = {667 post1: {id: 'post1', channel_id: 'channel1', create_at: 4000},668 post2: {id: 'post2', channel_id: 'channel1', create_at: 3000},669 post3: {id: 'post3', channel_id: 'channel1', create_at: 2000},670 post4: {id: 'post4', channel_id: 'channel1', create_at: 1000},671 };672 const nextState = reducers.postsInChannel(state, {673 type: PostTypes.RECEIVED_POSTS_IN_CHANNEL,674 channelId: 'channel1',675 data: {676 posts: {677 post1: nextPosts.post1,678 post3: nextPosts.post3,679 },680 order: ['post1', 'post3'],681 },682 recent: true,683 }, null, nextPosts);684 expect(nextState).not.toBe(state);685 expect(nextState).toEqual({686 channel1: [687 {order: ['post1', 'post2', 'post3', 'post4'], recent: true},688 ],689 });690 });691 it('should not save duplicate posts', () => {692 const state = deepFreeze({693 channel1: [694 {order: ['post1', 'post2', 'post3'], recent: true},695 ],696 });697 const nextPosts = {698 post1: {id: 'post1', channel_id: 'channel1', create_at: 4000},699 post2: {id: 'post2', channel_id: 'channel1', create_at: 3000},700 post3: {id: 'post3', channel_id: 'channel1', create_at: 2000},701 post4: {id: 'post4', channel_id: 'channel1', create_at: 1000},702 };703 const nextState = reducers.postsInChannel(state, {704 type: PostTypes.RECEIVED_POSTS_IN_CHANNEL,705 channelId: 'channel1',706 data: {707 posts: {708 post2: nextPosts.post2,709 post4: nextPosts.post4,710 },711 order: ['post2', 'post4'],712 },713 recent: true,714 }, null, nextPosts);715 expect(nextState).not.toBe(state);716 expect(nextState).toEqual({717 channel1: [718 {order: ['post1', 'post2', 'post3', 'post4'], recent: true},719 ],720 });721 });722 it('should do nothing when receiving no posts for loaded channel', () => {723 const state = deepFreeze({724 channel1: [725 {order: ['post1', 'post2', 'post3'], recent: true},726 ],727 });728 const nextState = reducers.postsInChannel(state, {729 type: PostTypes.RECEIVED_POSTS_IN_CHANNEL,730 channelId: 'channel1',731 data: {732 posts: {},733 order: [],734 },735 recent: true,736 }, null, {});737 expect(nextState).toBe(state);738 expect(nextState).toEqual({739 channel1: [740 {order: ['post1', 'post2', 'post3'], recent: true},741 ],742 });743 });744 it('should make entry for channel with no posts', () => {745 const state = deepFreeze({});746 const nextState = reducers.postsInChannel(state, {747 type: PostTypes.RECEIVED_POSTS_IN_CHANNEL,748 channelId: 'channel1',749 data: {750 posts: {},751 order: [],752 },753 recent: true,754 }, null, {});755 expect(nextState).not.toBe(state);756 expect(nextState).toEqual({757 channel1: [{758 order: [],759 recent: true,760 }],761 });762 });763 it('should not save posts that are not in data.order', () => {764 const state = deepFreeze({765 channel1: [766 {order: ['post2', 'post3'], recent: true},767 ],768 });769 const nextPosts = {770 post1: {id: 'post1', channel_id: 'channel1', create_at: 4000},771 post2: {id: 'post2', channel_id: 'channel1', create_at: 3000},772 post3: {id: 'post3', channel_id: 'channel1', create_at: 2000},773 post4: {id: 'post4', channel_id: 'channel1', create_at: 1000},774 };775 const nextState = reducers.postsInChannel(state, {776 type: PostTypes.RECEIVED_POSTS_IN_CHANNEL,777 channelId: 'channel1',778 data: {779 posts: {780 post1: nextPosts.post1,781 post2: nextPosts.post2,782 post3: nextPosts.post3,783 post4: nextPosts.post4,784 },785 order: ['post1', 'post2'],786 },787 recent: true,788 }, null, nextPosts);789 expect(nextState).not.toBe(state);790 expect(nextState).toEqual({791 channel1: [792 {order: ['post1', 'post2', 'post3'], recent: true},793 ],794 });795 });796 it('should not save posts in an older block, even if they may be adjacent', () => {797 const state = deepFreeze({798 channel1: [799 {order: ['post3', 'post4'], recent: false},800 ],801 });802 const nextPosts = {803 post1: {id: 'post1', channel_id: 'channel1', create_at: 4000},804 post2: {id: 'post2', channel_id: 'channel1', create_at: 3000},805 post3: {id: 'post3', channel_id: 'channel1', create_at: 2000},806 post4: {id: 'post4', channel_id: 'channel1', create_at: 1000},807 };808 const nextState = reducers.postsInChannel(state, {809 type: PostTypes.RECEIVED_POSTS_IN_CHANNEL,810 channelId: 'channel1',811 data: {812 posts: {813 post1: nextPosts.post1,814 post2: nextPosts.post2,815 },816 order: ['post1', 'post2'],817 },818 recent: true,819 }, null, nextPosts);820 expect(nextState).not.toBe(state);821 expect(nextState).toEqual({822 channel1: [823 {order: ['post3', 'post4'], recent: false},824 {order: ['post1', 'post2'], recent: true},825 ],826 });827 });828 it('should not save posts in the recent block even if new posts may be adjacent', () => {829 const state = deepFreeze({830 channel1: [831 {order: ['post3', 'post4'], recent: true},832 ],833 });834 const nextPosts = {835 post1: {id: 'post1', channel_id: 'channel1', create_at: 4000},836 post2: {id: 'post2', channel_id: 'channel1', create_at: 3000},837 post3: {id: 'post3', channel_id: 'channel1', create_at: 2000},838 post4: {id: 'post4', channel_id: 'channel1', create_at: 1000},839 };840 const nextState = reducers.postsInChannel(state, {841 type: PostTypes.RECEIVED_POSTS_IN_CHANNEL,842 channelId: 'channel1',843 data: {844 posts: {845 post1: nextPosts.post1,846 post2: nextPosts.post2,847 },848 order: ['post1', 'post2'],849 },850 recent: true,851 }, null, nextPosts);852 expect(nextState).not.toBe(state);853 expect(nextState).toEqual({854 channel1: [855 {order: ['post3', 'post4'], recent: false},856 {order: ['post1', 'post2'], recent: true},857 ],858 });859 });860 it('should add posts to non-recent block if there is overlap', () => {861 const state = deepFreeze({862 channel1: [863 {order: ['post2', 'post3'], recent: false},864 ],865 });866 const nextPosts = {867 post1: {id: 'post1', channel_id: 'channel1', create_at: 4000},868 post2: {id: 'post2', channel_id: 'channel1', create_at: 3000},869 post3: {id: 'post3', channel_id: 'channel1', create_at: 2000},870 };871 const nextState = reducers.postsInChannel(state, {872 type: PostTypes.RECEIVED_POSTS_IN_CHANNEL,873 channelId: 'channel1',874 data: {875 posts: {876 post1: nextPosts.post1,877 post2: nextPosts.post2,878 },879 order: ['post1', 'post2'],880 },881 recent: true,882 }, null, nextPosts);883 expect(nextState).not.toBe(state);884 expect(nextState).toEqual({885 channel1: [886 {order: ['post1', 'post2', 'post3'], recent: true},887 ],888 });889 });890 });891 describe('receiving consecutive posts in the channel that are not recent', () => {892 it('should save posts in the correct order', () => {893 const state = deepFreeze({894 channel1: [895 {order: ['post2', 'post4'], recent: false},896 ],897 });898 const nextPosts = {899 post1: {id: 'post1', channel_id: 'channel1', create_at: 4000},900 post2: {id: 'post2', channel_id: 'channel1', create_at: 3000},901 post3: {id: 'post3', channel_id: 'channel1', create_at: 2000},902 post4: {id: 'post4', channel_id: 'channel1', create_at: 1000},903 };904 const nextState = reducers.postsInChannel(state, {905 type: PostTypes.RECEIVED_POSTS_IN_CHANNEL,906 channelId: 'channel1',907 data: {908 posts: {909 post1: nextPosts.post1,910 post3: nextPosts.post3,911 },912 order: ['post1', 'post3'],913 },914 recent: false,915 }, null, nextPosts);916 expect(nextState).not.toBe(state);917 expect(nextState).toEqual({918 channel1: [919 {order: ['post1', 'post2', 'post3', 'post4'], recent: false},920 ],921 });922 });923 it('should not save duplicate posts', () => {924 const state = deepFreeze({925 channel1: [926 {order: ['post1', 'post2', 'post3'], recent: false},927 ],928 });929 const nextPosts = {930 post1: {id: 'post1', channel_id: 'channel1', create_at: 4000},931 post2: {id: 'post2', channel_id: 'channel1', create_at: 3000},932 post3: {id: 'post3', channel_id: 'channel1', create_at: 2000},933 post4: {id: 'post4', channel_id: 'channel1', create_at: 1000},934 };935 const nextState = reducers.postsInChannel(state, {936 type: PostTypes.RECEIVED_POSTS_IN_CHANNEL,937 channelId: 'channel1',938 data: {939 posts: {940 post2: nextPosts.post2,941 post4: nextPosts.post4,942 },943 order: ['post2', 'post4'],944 },945 recent: false,946 }, null, nextPosts);947 expect(nextState).not.toBe(state);948 expect(nextState).toEqual({949 channel1: [950 {order: ['post1', 'post2', 'post3', 'post4'], recent: false},951 ],952 });953 });954 it('should do nothing when receiving no posts for loaded channel', () => {955 const state = deepFreeze({956 channel1: [957 {order: ['post1', 'post2', 'post3'], recent: true},958 ],959 });960 const nextState = reducers.postsInChannel(state, {961 type: PostTypes.RECEIVED_POSTS_IN_CHANNEL,962 channelId: 'channel1',963 data: {964 posts: {},965 order: [],966 },967 recent: false,968 }, null, {});969 expect(nextState).toBe(state);970 expect(nextState).toEqual({971 channel1: [972 {order: ['post1', 'post2', 'post3'], recent: true},973 ],974 });975 });976 it('should make entry for channel with no posts', () => {977 const state = deepFreeze({});978 const nextState = reducers.postsInChannel(state, {979 type: PostTypes.RECEIVED_POSTS_IN_CHANNEL,980 channelId: 'channel1',981 data: {982 posts: {},983 order: [],984 },985 recent: false,986 }, null, {});987 expect(nextState).not.toBe(state);988 expect(nextState).toEqual({989 channel1: [{990 order: [],991 recent: false,992 }],993 });994 });995 it('should not save posts that are not in data.order', () => {996 const state = deepFreeze({997 channel1: [998 {order: ['post2', 'post3'], recent: false},999 ],1000 });1001 const nextPosts = {1002 post1: {id: 'post1', channel_id: 'channel1', create_at: 4000},1003 post2: {id: 'post2', channel_id: 'channel1', create_at: 3000},1004 post3: {id: 'post3', channel_id: 'channel1', create_at: 2000},1005 post4: {id: 'post4', channel_id: 'channel1', create_at: 1000},1006 };1007 const nextState = reducers.postsInChannel(state, {1008 type: PostTypes.RECEIVED_POSTS_IN_CHANNEL,1009 channelId: 'channel1',1010 data: {1011 posts: {1012 post1: nextPosts.post1,1013 post2: nextPosts.post2,1014 post3: nextPosts.post3,1015 post4: nextPosts.post4,1016 },1017 order: ['post1', 'post2'],1018 },1019 recent: false,1020 }, null, nextPosts);1021 expect(nextState).not.toBe(state);1022 expect(nextState).toEqual({1023 channel1: [1024 {order: ['post1', 'post2', 'post3'], recent: false},1025 ],1026 });1027 });1028 it('should not save posts in another block without overlap', () => {1029 const state = deepFreeze({1030 channel1: [1031 {order: ['post3', 'post4'], recent: false},1032 ],1033 });1034 const nextPosts = {1035 post1: {id: 'post1', channel_id: 'channel1', create_at: 4000},1036 post2: {id: 'post2', channel_id: 'channel1', create_at: 3000},1037 post3: {id: 'post3', channel_id: 'channel1', create_at: 2000},1038 post4: {id: 'post4', channel_id: 'channel1', create_at: 1000},1039 };1040 const nextState = reducers.postsInChannel(state, {1041 type: PostTypes.RECEIVED_POSTS_IN_CHANNEL,1042 channelId: 'channel1',1043 data: {1044 posts: {1045 post1: nextPosts.post1,1046 post2: nextPosts.post2,1047 },1048 order: ['post1', 'post2'],1049 },1050 recent: false,1051 }, null, nextPosts);1052 expect(nextState).not.toBe(state);1053 expect(nextState).toEqual({1054 channel1: [1055 {order: ['post3', 'post4'], recent: false},1056 {order: ['post1', 'post2'], recent: false},1057 ],1058 });1059 });1060 it('should add posts to recent block if there is overlap', () => {1061 const state = deepFreeze({1062 channel1: [1063 {order: ['post1', 'post2'], recent: true},1064 ],1065 });1066 const nextPosts = {1067 post1: {id: 'post1', channel_id: 'channel1', create_at: 4000},1068 post2: {id: 'post2', channel_id: 'channel1', create_at: 3000},1069 post3: {id: 'post3', channel_id: 'channel1', create_at: 2000},1070 post4: {id: 'post4', channel_id: 'channel1', create_at: 1000},1071 };1072 const nextState = reducers.postsInChannel(state, {1073 type: PostTypes.RECEIVED_POSTS_IN_CHANNEL,1074 channelId: 'channel1',1075 data: {1076 posts: {1077 post2: nextPosts.post2,1078 post3: nextPosts.post3,1079 },1080 order: ['post2', 'post3'],1081 },1082 recent: false,1083 }, null, nextPosts);1084 expect(nextState).not.toBe(state);1085 expect(nextState).toEqual({1086 channel1: [1087 {order: ['post1', 'post2', 'post3'], recent: true},1088 ],1089 });1090 });1091 it('should save with chunk as oldest', () => {1092 const state = deepFreeze({1093 channel1: [1094 {order: ['post1', 'post2'], recent: true},1095 ],1096 });1097 const nextPosts = {1098 post1: {id: 'post1', channel_id: 'channel1', create_at: 4000},1099 post2: {id: 'post2', channel_id: 'channel1', create_at: 3000},1100 post3: {id: 'post3', channel_id: 'channel1', create_at: 2000},1101 post4: {id: 'post4', channel_id: 'channel1', create_at: 1000},1102 };1103 const nextState = reducers.postsInChannel(state, {1104 type: PostTypes.RECEIVED_POSTS_IN_CHANNEL,1105 channelId: 'channel1',1106 data: {1107 posts: {1108 post2: nextPosts.post2,1109 post3: nextPosts.post3,1110 },1111 order: ['post2', 'post3'],1112 },1113 recent: false,1114 oldest: true,1115 }, null, nextPosts);1116 expect(nextState).not.toBe(state);1117 expect(nextState).toEqual({1118 channel1: [1119 {order: ['post1', 'post2', 'post3'], recent: true, oldest: true},1120 ],1121 });1122 });1123 });1124 describe('receiving posts since', () => {1125 it('should save posts in the channel in the correct order', () => {1126 const state = deepFreeze({1127 channel1: [1128 {order: ['post3', 'post4'], recent: true},1129 ],1130 });1131 const nextPosts = {1132 post1: {id: 'post1', channel_id: 'channel1', create_at: 4000},1133 post2: {id: 'post2', channel_id: 'channel1', create_at: 3000},1134 post3: {id: 'post3', channel_id: 'channel1', create_at: 2000},1135 post4: {id: 'post4', channel_id: 'channel1', create_at: 1000},1136 };1137 const nextState = reducers.postsInChannel(state, {1138 type: PostTypes.RECEIVED_POSTS_SINCE,1139 channelId: 'channel1',1140 data: {1141 posts: {1142 post1: nextPosts.post1,1143 post2: nextPosts.post2,1144 },1145 order: ['post1', 'post2'],1146 },1147 }, null, nextPosts);1148 expect(nextState).not.toBe(state);1149 expect(nextState).toEqual({1150 channel1: [1151 {order: ['post1', 'post2', 'post3', 'post4'], recent: true},1152 ],1153 });1154 });1155 it('should not save older posts', () => {1156 const state = deepFreeze({1157 channel1: [1158 {order: ['post2', 'post3'], recent: true},1159 ],1160 });1161 const nextPosts = {1162 post1: {id: 'post1', channel_id: 'channel1', create_at: 4000},1163 post2: {id: 'post2', channel_id: 'channel1', create_at: 3000},1164 post3: {id: 'post3', channel_id: 'channel1', create_at: 2000},1165 post4: {id: 'post4', channel_id: 'channel1', create_at: 1000},1166 };1167 const nextState = reducers.postsInChannel(state, {1168 type: PostTypes.RECEIVED_POSTS_SINCE,1169 channelId: 'channel1',1170 data: {1171 posts: {1172 post1: nextPosts.post1,1173 post4: nextPosts.post4,1174 },1175 order: ['post1', 'post4'],1176 },1177 }, null, nextPosts);1178 expect(nextState).not.toBe(state);1179 expect(nextState).toEqual({1180 channel1: [1181 {order: ['post1', 'post2', 'post3'], recent: true},1182 ],1183 });1184 });1185 it('should save any posts in between', () => {1186 const state = deepFreeze({1187 channel1: [1188 {order: ['post2', 'post4'], recent: true},1189 ],1190 });1191 const nextPosts = {1192 post1: {id: 'post1', channel_id: 'channel1', create_at: 4000},1193 post2: {id: 'post2', channel_id: 'channel1', create_at: 3000},1194 post3: {id: 'post3', channel_id: 'channel1', create_at: 2000},1195 post4: {id: 'post4', channel_id: 'channel1', create_at: 1000},1196 post5: {id: 'post5', channel_id: 'channel1', create_at: 500},1197 post6: {id: 'post6', channel_id: 'channel1', create_at: 300},1198 };1199 const nextState = reducers.postsInChannel(state, {1200 type: PostTypes.RECEIVED_POSTS_SINCE,1201 channelId: 'channel1',1202 data: {1203 posts: {1204 post1: nextPosts.post1,1205 post2: nextPosts.post2,1206 post3: nextPosts.post5,1207 post4: nextPosts.post4,1208 post5: nextPosts.post5,1209 post6: nextPosts.post6,1210 },1211 order: ['post1', 'post2', 'post3', 'post4', 'post5', 'post6'],1212 },1213 }, null, nextPosts);1214 expect(nextState).not.toBe(state);1215 expect(nextState).toEqual({1216 channel1: [1217 {order: ['post1', 'post2', 'post3', 'post4'], recent: true},1218 ],1219 });1220 });1221 it('should do nothing if only receiving updated posts', () => {1222 const state = deepFreeze({1223 channel1: [1224 {order: ['post1', 'post2', 'post3', 'post4'], recent: true},1225 ],1226 });1227 const nextPosts = {1228 post1: {id: 'post1', channel_id: 'channel1', create_at: 4000},1229 post2: {id: 'post2', channel_id: 'channel1', create_at: 3000},1230 post3: {id: 'post3', channel_id: 'channel1', create_at: 2000},1231 post4: {id: 'post4', channel_id: 'channel1', create_at: 1000},1232 };1233 const nextState = reducers.postsInChannel(state, {1234 type: PostTypes.RECEIVED_POSTS_SINCE,1235 channelId: 'channel1',1236 data: {1237 posts: {1238 post1: nextPosts.post1,1239 post4: nextPosts.post4,1240 },1241 order: ['post1', 'post4'],1242 },1243 }, null, nextPosts);1244 expect(nextState).toBe(state);1245 expect(nextState).toEqual({1246 channel1: [1247 {order: ['post1', 'post2', 'post3', 'post4'], recent: true},1248 ],1249 });1250 });1251 it('should not save duplicate posts', () => {1252 const state = deepFreeze({1253 channel1: [1254 {order: ['post2', 'post3'], recent: true},1255 ],1256 });1257 const nextPosts = {1258 post1: {id: 'post1', channel_id: 'channel1', create_at: 4000},1259 post2: {id: 'post2', channel_id: 'channel1', create_at: 3000},1260 post3: {id: 'post3', channel_id: 'channel1', create_at: 2000},1261 };1262 const nextState = reducers.postsInChannel(state, {1263 type: PostTypes.RECEIVED_POSTS_SINCE,1264 channelId: 'channel1',1265 data: {1266 posts: {1267 post1: nextPosts.post1,1268 post2: nextPosts.post2,1269 },1270 order: ['post1', 'post2'],1271 },1272 }, null, nextPosts);1273 expect(nextState).not.toBe(state);1274 expect(nextState).toEqual({1275 channel1: [1276 {order: ['post1', 'post2', 'post3'], recent: true},1277 ],1278 });1279 });1280 it('should do nothing when receiving no posts for loaded channel', () => {1281 const state = deepFreeze({1282 channel1: [1283 {order: ['post1', 'post2', 'post3'], recent: true},1284 ],1285 });1286 const nextState = reducers.postsInChannel(state, {1287 type: PostTypes.RECEIVED_POSTS_SINCE,1288 channelId: 'channel1',1289 data: {1290 posts: {},1291 order: [],1292 },1293 }, null, {});1294 expect(nextState).toBe(state);1295 expect(nextState).toEqual({1296 channel1: [1297 {order: ['post1', 'post2', 'post3'], recent: true},1298 ],1299 });1300 });1301 it('should do nothing for channel with no posts', () => {1302 const state = deepFreeze({});1303 const nextState = reducers.postsInChannel(state, {1304 type: PostTypes.RECEIVED_POSTS_SINCE,1305 channelId: 'channel1',1306 data: {1307 posts: {},1308 order: [],1309 },1310 page: 0,1311 }, null, {});1312 expect(nextState).toBe(state);1313 expect(nextState).toEqual({});1314 });1315 it('should not save posts that are not in data.order', () => {1316 const state = deepFreeze({1317 channel1: [1318 {order: ['post2', 'post3'], recent: true},1319 ],1320 });1321 const nextPosts = {1322 post1: {id: 'post1', channel_id: 'channel1', create_at: 4000},1323 post2: {id: 'post2', channel_id: 'channel1', create_at: 3000},1324 post3: {id: 'post3', channel_id: 'channel1', create_at: 2000},1325 post4: {id: 'post4', channel_id: 'channel1', create_at: 1000},1326 };1327 const nextState = reducers.postsInChannel(state, {1328 type: PostTypes.RECEIVED_POSTS_SINCE,1329 channelId: 'channel1',1330 data: {1331 posts: {1332 post1: nextPosts.post1,1333 post4: nextPosts.post4,1334 },1335 order: ['post1'],1336 },1337 }, null, nextPosts);1338 expect(nextState).not.toBe(state);1339 expect(nextState).toEqual({1340 channel1: [1341 {order: ['post1', 'post2', 'post3'], recent: true},1342 ],1343 });1344 });1345 it('should not save posts in an older block', () => {1346 const state = deepFreeze({1347 channel1: [1348 {order: ['post3', 'post4'], recent: false},1349 ],1350 });1351 const nextPosts = {1352 post1: {id: 'post1', channel_id: 'channel1', create_at: 4000},1353 post2: {id: 'post2', channel_id: 'channel1', create_at: 3000},1354 post3: {id: 'post3', channel_id: 'channel1', create_at: 2000},1355 post4: {id: 'post4', channel_id: 'channel1', create_at: 1000},1356 };1357 const nextState = reducers.postsInChannel(state, {1358 type: PostTypes.RECEIVED_POSTS_SINCE,1359 channelId: 'channel1',1360 data: {1361 posts: {1362 post1: nextPosts.post1,1363 post2: nextPosts.post2,1364 },1365 order: ['post1', 'post2'],1366 },1367 }, null, nextPosts);1368 expect(nextState).toBe(state);1369 expect(nextState).toEqual({1370 channel1: [1371 {order: ['post3', 'post4'], recent: false},1372 ],1373 });1374 });1375 it('should always save posts in the recent block', () => {1376 const state = deepFreeze({1377 channel1: [1378 {order: ['post3', 'post4'], recent: true},1379 ],1380 });1381 const nextPosts = {1382 post1: {id: 'post1', channel_id: 'channel1', create_at: 4000},1383 post2: {id: 'post2', channel_id: 'channel1', create_at: 3000},1384 post3: {id: 'post3', channel_id: 'channel1', create_at: 2000},1385 post4: {id: 'post4', channel_id: 'channel1', create_at: 1000},1386 };1387 const nextState = reducers.postsInChannel(state, {1388 type: PostTypes.RECEIVED_POSTS_SINCE,1389 channelId: 'channel1',1390 data: {1391 posts: {1392 post1: nextPosts.post1,1393 post2: nextPosts.post2,1394 },1395 order: ['post1', 'post2'],1396 },1397 }, null, nextPosts);1398 expect(nextState).not.toBe(state);1399 expect(nextState).toEqual({1400 channel1: [1401 {order: ['post1', 'post2', 'post3', 'post4'], recent: true},1402 ],1403 });1404 });1405 });1406 describe('receiving posts after', () => {1407 it('should save posts when channel is not loaded', () => {1408 const state = deepFreeze({});1409 const nextPosts = {1410 post1: {id: 'post1', channel_id: 'channel1', create_at: 4000},1411 post2: {id: 'post2', channel_id: 'channel1', create_at: 3000},1412 post3: {id: 'post3', channel_id: 'channel1', create_at: 2000},1413 };1414 const nextState = reducers.postsInChannel(state, {1415 type: PostTypes.RECEIVED_POSTS_AFTER,1416 channelId: 'channel1',1417 data: {1418 posts: {1419 post1: nextPosts.post1,1420 post2: nextPosts.post2,1421 },1422 order: ['post1', 'post2'],1423 },1424 afterPostId: 'post3',1425 recent: false,1426 }, null, nextPosts);1427 expect(nextState).not.toBe(state);1428 expect(nextState).toEqual({1429 channel1: [1430 {order: ['post1', 'post2', 'post3'], recent: false},1431 ],1432 });1433 });1434 it('should save posts when channel is empty', () => {1435 const state = deepFreeze({1436 channel1: [],1437 });1438 const nextPosts = {1439 post1: {id: 'post1', channel_id: 'channel1', create_at: 4000},1440 post2: {id: 'post2', channel_id: 'channel1', create_at: 3000},1441 post3: {id: 'post3', channel_id: 'channel1', create_at: 2000},1442 };1443 const nextState = reducers.postsInChannel(state, {1444 type: PostTypes.RECEIVED_POSTS_AFTER,1445 channelId: 'channel1',1446 data: {1447 posts: {1448 post1: nextPosts.post1,1449 post2: nextPosts.post2,1450 },1451 order: ['post1', 'post2'],1452 },1453 afterPostId: 'post3',1454 recent: false,1455 }, null, nextPosts);1456 expect(nextState).not.toBe(state);1457 expect(nextState).toEqual({1458 channel1: [1459 {order: ['post1', 'post2', 'post3'], recent: false},1460 ],1461 });1462 });1463 it('should add posts to existing block', () => {1464 const state = deepFreeze({1465 channel1: [1466 {order: ['post3', 'post4'], recent: false},1467 ],1468 });1469 const nextPosts = {1470 post1: {id: 'post1', channel_id: 'channel1', create_at: 4000},1471 post2: {id: 'post2', channel_id: 'channel1', create_at: 3000},1472 post3: {id: 'post3', channel_id: 'channel1', create_at: 2000},1473 post4: {id: 'post4', channel_id: 'channel1', create_at: 1000},1474 };1475 const nextState = reducers.postsInChannel(state, {1476 type: PostTypes.RECEIVED_POSTS_AFTER,1477 channelId: 'channel1',1478 data: {1479 posts: {1480 post1: nextPosts.post1,1481 post2: nextPosts.post2,1482 },1483 order: ['post1', 'post2'],1484 },1485 afterPostId: 'post3',1486 }, null, nextPosts);1487 expect(nextState).not.toBe(state);1488 expect(nextState).toEqual({1489 channel1: [1490 {order: ['post1', 'post2', 'post3', 'post4'], recent: false},1491 ],1492 });1493 });1494 it('should merge adjacent posts if we have newer posts', () => {1495 const state = deepFreeze({1496 channel1: [1497 {order: ['post4'], recent: false},1498 {order: ['post1', 'post2'], recent: true},1499 ],1500 });1501 const nextPosts = {1502 post1: {id: 'post1', channel_id: 'channel1', create_at: 4000},1503 post2: {id: 'post2', channel_id: 'channel1', create_at: 3000},1504 post3: {id: 'post3', channel_id: 'channel1', create_at: 2000},1505 post4: {id: 'post4', channel_id: 'channel1', create_at: 1000},1506 };1507 const nextState = reducers.postsInChannel(state, {1508 type: PostTypes.RECEIVED_POSTS_AFTER,1509 channelId: 'channel1',1510 data: {1511 posts: {1512 post1: nextPosts.post1,1513 post3: nextPosts.post3,1514 },1515 order: ['post2', 'post3'],1516 },1517 afterPostId: 'post4',1518 }, null, nextPosts);1519 expect(nextState).not.toBe(state);1520 expect(nextState).toEqual({1521 channel1: [1522 {order: ['post1', 'post2', 'post3', 'post4'], recent: true},1523 ],1524 });1525 });1526 it('should do nothing when no posts are received', () => {1527 const state = deepFreeze({1528 channel1: [1529 {order: ['post1', 'post2'], recent: true},1530 ],1531 });1532 const nextPosts = {1533 post1: {id: 'post1', channel_id: 'channel1', create_at: 4000},1534 post2: {id: 'post2', channel_id: 'channel1', create_at: 3000},1535 };1536 const nextState = reducers.postsInChannel(state, {1537 type: PostTypes.RECEIVED_POSTS_AFTER,1538 channelId: 'channel1',1539 data: {1540 posts: {},1541 order: [],1542 },1543 afterPostId: 'post1',1544 }, null, nextPosts);1545 expect(nextState).toBe(state);1546 expect(nextState).toEqual({1547 channel1: [1548 {order: ['post1', 'post2'], recent: true},1549 ],1550 });1551 });1552 });1553 describe('receiving posts before', () => {1554 it('should save posts when channel is not loaded', () => {1555 const state = deepFreeze({});1556 const nextPosts = {1557 post1: {id: 'post1', channel_id: 'channel1', create_at: 4000},1558 post2: {id: 'post2', channel_id: 'channel1', create_at: 3000},1559 post3: {id: 'post3', channel_id: 'channel1', create_at: 2000},1560 };1561 const nextState = reducers.postsInChannel(state, {1562 type: PostTypes.RECEIVED_POSTS_BEFORE,1563 channelId: 'channel1',1564 data: {1565 posts: {1566 post2: nextPosts.post2,1567 post3: nextPosts.post3,1568 },1569 order: ['post2', 'post3'],1570 },1571 beforePostId: 'post1',1572 }, null, nextPosts);1573 expect(nextState).not.toBe(state);1574 expect(nextState).toEqual({1575 channel1: [1576 {order: ['post1', 'post2', 'post3'], recent: false},1577 ],1578 });1579 });1580 it('should have oldest set to false', () => {1581 const state = deepFreeze({});1582 const nextPosts = {1583 post1: {id: 'post1', channel_id: 'channel1', create_at: 4000},1584 post2: {id: 'post2', channel_id: 'channel1', create_at: 3000},1585 post3: {id: 'post3', channel_id: 'channel1', create_at: 2000},1586 };1587 const nextState = reducers.postsInChannel(state, {1588 type: PostTypes.RECEIVED_POSTS_BEFORE,1589 channelId: 'channel1',1590 data: {1591 posts: {1592 post2: nextPosts.post2,1593 post3: nextPosts.post3,1594 },1595 order: ['post2', 'post3'],1596 },1597 beforePostId: 'post1',1598 oldest: false,1599 }, null, nextPosts);1600 expect(nextState).not.toBe(state);1601 expect(nextState).toEqual({1602 channel1: [1603 {order: ['post1', 'post2', 'post3'], recent: false, oldest: false},1604 ],1605 });1606 });1607 it('should save posts when channel is empty', () => {1608 const state = deepFreeze({1609 channel1: [],1610 });1611 const nextPosts = {1612 post1: {id: 'post1', channel_id: 'channel1', create_at: 4000},1613 post2: {id: 'post2', channel_id: 'channel1', create_at: 3000},1614 post3: {id: 'post3', channel_id: 'channel1', create_at: 2000},1615 };1616 const nextState = reducers.postsInChannel(state, {1617 type: PostTypes.RECEIVED_POSTS_BEFORE,1618 channelId: 'channel1',1619 data: {1620 posts: {1621 post2: nextPosts.post2,1622 post3: nextPosts.post3,1623 },1624 order: ['post2', 'post3'],1625 },1626 beforePostId: 'post1',1627 }, null, nextPosts);1628 expect(nextState).not.toBe(state);1629 expect(nextState).toEqual({1630 channel1: [1631 {order: ['post1', 'post2', 'post3'], recent: false},1632 ],1633 });1634 });1635 it('should add posts to existing block', () => {1636 const state = deepFreeze({1637 channel1: [1638 {order: ['post1', 'post2'], recent: false},1639 ],1640 });1641 const nextPosts = {1642 post1: {id: 'post1', channel_id: 'channel1', create_at: 4000},1643 post2: {id: 'post2', channel_id: 'channel1', create_at: 3000},1644 post3: {id: 'post3', channel_id: 'channel1', create_at: 2000},1645 post4: {id: 'post4', channel_id: 'channel1', create_at: 1000},1646 };1647 const nextState = reducers.postsInChannel(state, {1648 type: PostTypes.RECEIVED_POSTS_BEFORE,1649 channelId: 'channel1',1650 data: {1651 posts: {1652 post3: nextPosts.post3,1653 post4: nextPosts.post4,1654 },1655 order: ['post3', 'post4'],1656 },1657 beforePostId: 'post2',1658 }, null, nextPosts);1659 expect(nextState).not.toBe(state);1660 expect(nextState).toEqual({1661 channel1: [1662 {order: ['post1', 'post2', 'post3', 'post4'], recent: false},1663 ],1664 });1665 });1666 it('should merge adjacent posts if we have newer posts', () => {1667 const state = deepFreeze({1668 channel1: [1669 {order: ['post4'], recent: false},1670 {order: ['post1'], recent: true},1671 ],1672 });1673 const nextPosts = {1674 post1: {id: 'post1', channel_id: 'channel1', create_at: 4000},1675 post2: {id: 'post2', channel_id: 'channel1', create_at: 3000},1676 post3: {id: 'post3', channel_id: 'channel1', create_at: 2000},1677 post4: {id: 'post4', channel_id: 'channel1', create_at: 1000},1678 };1679 const nextState = reducers.postsInChannel(state, {1680 type: PostTypes.RECEIVED_POSTS_BEFORE,1681 channelId: 'channel1',1682 data: {1683 posts: {1684 post1: nextPosts.post1,1685 post3: nextPosts.post3,1686 },1687 order: ['post2', 'post3', 'post4'],1688 },1689 beforePostId: 'post1',1690 }, null, nextPosts);1691 expect(nextState).not.toBe(state);1692 expect(nextState).toEqual({1693 channel1: [1694 {order: ['post1', 'post2', 'post3', 'post4'], recent: true},1695 ],1696 });1697 });1698 it('should do nothing when no posts are received', () => {1699 const state = deepFreeze({1700 channel1: [1701 {order: ['post1', 'post2'], recent: true},1702 ],1703 });1704 const nextPosts = {1705 post1: {id: 'post1', channel_id: 'channel1', create_at: 4000},1706 post2: {id: 'post2', channel_id: 'channel1', create_at: 3000},1707 };1708 const nextState = reducers.postsInChannel(state, {1709 type: PostTypes.RECEIVED_POSTS_BEFORE,1710 channelId: 'channel1',1711 data: {1712 posts: {},1713 order: [],1714 },1715 beforePostId: 'post2',1716 }, null, nextPosts);1717 expect(nextState).toBe(state);1718 expect(nextState).toEqual({1719 channel1: [1720 {order: ['post1', 'post2'], recent: true},1721 ],1722 });1723 });1724 });1725 describe('deleting a post', () => {1726 it('should do nothing when deleting a post without comments', () => {1727 const state = deepFreeze({1728 channel1: [1729 {order: ['post1', 'post2', 'post3'], recent: false},1730 ],1731 });1732 const prevPosts = {1733 post1: {id: 'post1', channel_id: 'channel1'},1734 post2: {id: 'post2', channel_id: 'channel1'},1735 post3: {id: 'post3', channel_id: 'channel1'},1736 };1737 const nextState = reducers.postsInChannel(state, {1738 type: PostTypes.POST_DELETED,1739 data: prevPosts.post2,1740 }, prevPosts, null);1741 expect(nextState).toBe(state);1742 expect(nextState).toEqual({1743 channel1: [1744 {order: ['post1', 'post2', 'post3'], recent: false},1745 ],1746 });1747 });1748 it('should remove comments on the post when deleting a post with comments', () => {1749 const state = deepFreeze({1750 channel1: [1751 {order: ['post1', 'post2', 'post3', 'post4'], recent: false},1752 ],1753 });1754 const prevPosts = {1755 post1: {id: 'post1', channel_id: 'channel1', root_id: 'post4'},1756 post2: {id: 'post2', channel_id: 'channel1', root_id: 'post3'},1757 post3: {id: 'post3', channel_id: 'channel1'},1758 post4: {id: 'post4', channel_id: 'channel1'},1759 };1760 const nextState = reducers.postsInChannel(state, {1761 type: PostTypes.POST_DELETED,1762 data: prevPosts.post3,1763 }, prevPosts, null);1764 expect(nextState).not.toBe(state);1765 expect(nextState).toEqual({1766 channel1: [1767 {order: ['post1', 'post3', 'post4'], recent: false},1768 ],1769 });1770 });1771 it('should remove comments from multiple blocks', () => {1772 const state = deepFreeze({1773 channel1: [1774 {order: ['post1', 'post2'], recent: false},1775 {order: ['post3', 'post4'], recent: false},1776 ],1777 });1778 const prevPosts = {1779 post1: {id: 'post1', channel_id: 'channel1', root_id: 'post4'},1780 post2: {id: 'post2', channel_id: 'channel1'},1781 post3: {id: 'post3', channel_id: 'channel1', root_id: 'post4'},1782 post4: {id: 'post4', channel_id: 'channel1'},1783 };1784 const nextState = reducers.postsInChannel(state, {1785 type: PostTypes.POST_DELETED,1786 data: prevPosts.post4,1787 }, prevPosts, null);1788 expect(nextState).not.toBe(state);1789 expect(nextState).toEqual({1790 channel1: [1791 {order: ['post2'], recent: false},1792 {order: ['post4'], recent: false},1793 ],1794 });1795 });1796 it('should do nothing to blocks without comments', () => {1797 const state = deepFreeze({1798 channel1: [1799 {order: ['post1', 'post2'], recent: false},1800 {order: ['post3', 'post4'], recent: false},1801 ],1802 });1803 const prevPosts = {1804 post1: {id: 'post1', channel_id: 'channel1'},1805 post2: {id: 'post2', channel_id: 'channel1'},1806 post3: {id: 'post3', channel_id: 'channel1', root_id: 'post4'},1807 post4: {id: 'post4', channel_id: 'channel1'},1808 };1809 const nextState = reducers.postsInChannel(state, {1810 type: PostTypes.POST_DELETED,1811 data: prevPosts.post4,1812 }, prevPosts, null);1813 expect(nextState).not.toBe(state);1814 expect(nextState[0]).toBe(state[0]);1815 expect(nextState).toEqual({1816 channel1: [1817 {order: ['post1', 'post2'], recent: false},1818 {order: ['post4'], recent: false},1819 ],1820 });1821 });1822 it('should do nothing when deleting a comment', () => {1823 const state = deepFreeze({1824 channel1: [1825 {order: ['post1', 'post2', 'post3', 'post4'], recent: false},1826 ],1827 });1828 const prevPosts = {1829 post1: {id: 'post1', channel_id: 'channel1', root_id: 'post4'},1830 post2: {id: 'post2', channel_id: 'channel1', root_id: 'post3'},1831 post3: {id: 'post3', channel_id: 'channel1'},1832 post4: {id: 'post4', channel_id: 'channel1'},1833 };1834 const nextState = reducers.postsInChannel(state, {1835 type: PostTypes.POST_DELETED,1836 data: prevPosts.post2,1837 }, prevPosts, null);1838 expect(nextState).toBe(state);1839 expect(nextState).toEqual({1840 channel1: [1841 {order: ['post1', 'post2', 'post3', 'post4'], recent: false},1842 ],1843 });1844 });1845 it('should do nothing if the post has not been loaded', () => {1846 const state = deepFreeze({1847 channel1: [1848 {order: ['post1', 'post2', 'post3'], recent: false},1849 ],1850 });1851 const prevPosts = {1852 post1: {id: 'post1', channel_id: 'channel1'},1853 post2: {id: 'post2', channel_id: 'channel1'},1854 post3: {id: 'post3', channel_id: 'channel1'},1855 post4: {id: 'post4', channel_id: 'channel1'},1856 };1857 const nextState = reducers.postsInChannel(state, {1858 type: PostTypes.POST_DELETED,1859 data: prevPosts.post4,1860 }, prevPosts, null);1861 expect(nextState).toBe(state);1862 expect(nextState).toEqual({1863 channel1: [1864 {order: ['post1', 'post2', 'post3'], recent: false},1865 ],1866 });1867 });1868 it('should do nothing if no posts in the channel have been loaded', () => {1869 const state = deepFreeze({});1870 const prevPosts = {1871 post1: {id: 'post1', channel_id: 'channel1'},1872 post2: {id: 'post2', channel_id: 'channel1'},1873 post3: {id: 'post3', channel_id: 'channel1'},1874 };1875 const nextState = reducers.postsInChannel(state, {1876 type: PostTypes.POST_DELETED,1877 data: prevPosts.post1,1878 }, prevPosts, null);1879 expect(nextState).toBe(state);1880 expect(nextState).toEqual({});1881 });1882 it('should remove empty blocks', () => {1883 const state = deepFreeze({1884 channel1: [1885 {order: ['post1', 'post2'], recent: false},1886 {order: ['post3', 'post4'], recent: false},1887 ],1888 });1889 const prevPosts = {1890 post1: {id: 'post1', channel_id: 'channel1', root_id: 'post4'},1891 post2: {id: 'post2', channel_id: 'channel1', root_id: 'post4'},1892 post3: {id: 'post3', channel_id: 'channel1', root_id: 'post4'},1893 post4: {id: 'post4', channel_id: 'channel1'},1894 };1895 const nextState = reducers.postsInChannel(state, {1896 type: PostTypes.POST_DELETED,1897 data: prevPosts.post4,1898 }, prevPosts, null);1899 expect(nextState).not.toBe(state);1900 expect(nextState).toEqual({1901 channel1: [1902 {order: ['post4'], recent: false},1903 ],1904 });1905 });1906 });1907 describe('removing a post', () => {1908 it('should remove the post', () => {1909 const state = deepFreeze({1910 channel1: [1911 {order: ['post1', 'post2', 'post3'], recent: false},1912 ],1913 });1914 const prevPosts = {1915 post1: {id: 'post1', channel_id: 'channel1'},1916 post2: {id: 'post2', channel_id: 'channel1'},1917 post3: {id: 'post3', channel_id: 'channel1'},1918 };1919 const nextState = reducers.postsInChannel(state, {1920 type: PostTypes.POST_REMOVED,1921 data: prevPosts.post2,1922 }, prevPosts, null);1923 expect(nextState).not.toBe(state);1924 expect(nextState).toEqual({1925 channel1: [1926 {order: ['post1', 'post3'], recent: false},1927 ],1928 });1929 });1930 it('should remove comments on the post', () => {1931 const state = deepFreeze({1932 channel1: [1933 {order: ['post1', 'post2', 'post3', 'post4'], recent: false},1934 ],1935 });1936 const prevPosts = {1937 post1: {id: 'post1', channel_id: 'channel1', root_id: 'post4'},1938 post2: {id: 'post2', channel_id: 'channel1', root_id: 'post3'},1939 post3: {id: 'post3', channel_id: 'channel1'},1940 post4: {id: 'post4', channel_id: 'channel1'},1941 };1942 const nextState = reducers.postsInChannel(state, {1943 type: PostTypes.POST_REMOVED,1944 data: prevPosts.post3,1945 }, prevPosts, null);1946 expect(nextState).not.toBe(state);1947 expect(nextState).toEqual({1948 channel1: [1949 {order: ['post1', 'post4'], recent: false},1950 ],1951 });1952 });1953 it('should remove a comment without removing the root post', () => {1954 const state = deepFreeze({1955 channel1: [1956 {order: ['post1', 'post2', 'post3', 'post4'], recent: false},1957 ],1958 });1959 const prevPosts = {1960 post1: {id: 'post1', channel_id: 'channel1', root_id: 'post4'},1961 post2: {id: 'post2', channel_id: 'channel1', root_id: 'post3'},1962 post3: {id: 'post3', channel_id: 'channel1'},1963 post4: {id: 'post4', channel_id: 'channel1'},1964 };1965 const nextState = reducers.postsInChannel(state, {1966 type: PostTypes.POST_REMOVED,1967 data: prevPosts.post2,1968 }, prevPosts, null);1969 expect(nextState).not.toBe(state);1970 expect(nextState).toEqual({1971 channel1: [1972 {order: ['post1', 'post3', 'post4'], recent: false},1973 ],1974 });1975 });1976 it('should do nothing if the post has not been loaded', () => {1977 const state = deepFreeze({1978 channel1: [1979 {order: ['post1', 'post2', 'post3'], recent: false},1980 ],1981 });1982 const prevPosts = {1983 post1: {id: 'post1', channel_id: 'channel1'},1984 post2: {id: 'post2', channel_id: 'channel1'},1985 post3: {id: 'post3', channel_id: 'channel1'},1986 post4: {id: 'post4', channel_id: 'channel1'},1987 };1988 const nextState = reducers.postsInChannel(state, {1989 type: PostTypes.POST_REMOVED,1990 data: prevPosts.post4,1991 }, prevPosts, null);1992 expect(nextState).toBe(state);1993 expect(nextState).toEqual({1994 channel1: [1995 {order: ['post1', 'post2', 'post3'], recent: false},1996 ],1997 });1998 });1999 it('should do nothing if no posts in the channel have been loaded', () => {2000 const state = deepFreeze({});2001 const prevPosts = {2002 post1: {id: 'post1', channel_id: 'channel1'},2003 post2: {id: 'post2', channel_id: 'channel1'},2004 post3: {id: 'post3', channel_id: 'channel1'},2005 };2006 const nextState = reducers.postsInChannel(state, {2007 type: PostTypes.POST_REMOVED,2008 data: prevPosts.post1,2009 }, prevPosts, null);2010 expect(nextState).toBe(state);2011 expect(nextState).toEqual({});2012 });2013 it('should remove empty blocks', () => {2014 const state = deepFreeze({2015 channel1: [2016 {order: ['post1', 'post2'], recent: false},2017 {order: ['post3', 'post4'], recent: false},2018 ],2019 });2020 const prevPosts = {2021 post1: {id: 'post1', channel_id: 'channel1', root_id: 'post4'},2022 post2: {id: 'post2', channel_id: 'channel1'},2023 post3: {id: 'post3', channel_id: 'channel1', root_id: 'post4'},2024 post4: {id: 'post4', channel_id: 'channel1'},2025 };2026 const nextState = reducers.postsInChannel(state, {2027 type: PostTypes.POST_REMOVED,2028 data: prevPosts.post4,2029 }, prevPosts, null);2030 expect(nextState).not.toBe(state);2031 expect(nextState).toEqual({2032 channel1: [2033 {order: ['post2'], recent: false},2034 ],2035 });2036 });2037 });2038 for (const actionType of [2039 ChannelTypes.RECEIVED_CHANNEL_DELETED,2040 ChannelTypes.DELETE_CHANNEL_SUCCESS,2041 ChannelTypes.LEAVE_CHANNEL,2042 ]) {2043 describe(`when a channel is deleted (${actionType})`, () => {2044 it('should remove any posts in that channel', () => {2045 const state = deepFreeze({2046 channel1: [2047 {order: ['post1', 'post2', 'post3'], recent: false},2048 {order: ['post6', 'post7', 'post8'], recent: false},2049 ],2050 channel2: [2051 {order: ['post4', 'post5'], recent: false},2052 ],2053 });2054 const nextState = reducers.postsInChannel(state, {2055 type: actionType,2056 data: {2057 id: 'channel1',2058 viewArchivedChannels: false,2059 },2060 });2061 expect(nextState).not.toBe(state);2062 expect(nextState.channel2).toBe(state.channel2);2063 expect(nextState).toEqual({2064 channel2: [2065 {order: ['post4', 'post5'], recent: false},2066 ],2067 });2068 });2069 it('should do nothing if no posts in that channel are loaded', () => {2070 const state = deepFreeze({2071 channel1: [2072 {order: ['post1', 'post2', 'post3'], recent: false},2073 ],2074 channel2: [2075 {order: ['post4', 'post5'], recent: false},2076 ],2077 });2078 const nextState = reducers.postsInChannel(state, {2079 type: actionType,2080 data: {2081 id: 'channel3',2082 viewArchivedChannels: false,2083 },2084 });2085 expect(nextState).toBe(state);2086 expect(nextState.channel1).toBe(state.channel1);2087 expect(nextState.channel2).toBe(state.channel2);2088 expect(nextState).toEqual({2089 channel1: [2090 {order: ['post1', 'post2', 'post3'], recent: false},2091 ],2092 channel2: [2093 {order: ['post4', 'post5'], recent: false},2094 ],2095 });2096 });2097 it('should not remove any posts with viewArchivedChannels enabled', () => {2098 const state = deepFreeze({2099 channel1: [2100 {order: ['post1', 'post2', 'post3'], recent: false},2101 {order: ['post6', 'post7', 'post8'], recent: false},2102 ],2103 channel2: [2104 {order: ['post4', 'post5'], recent: false},2105 ],2106 });2107 const nextState = reducers.postsInChannel(state, {2108 type: actionType,2109 data: {2110 id: 'channel1',2111 viewArchivedChannels: true,2112 },2113 });2114 expect(nextState).toBe(state);2115 expect(nextState.channel1).toBe(state.channel1);2116 expect(nextState.channel2).toBe(state.channel2);2117 expect(nextState).toEqual({2118 channel1: [2119 {order: ['post1', 'post2', 'post3'], recent: false},2120 {order: ['post6', 'post7', 'post8'], recent: false},2121 ],2122 channel2: [2123 {order: ['post4', 'post5'], recent: false},2124 ],2125 });2126 });2127 });2128 }2129});2130describe('mergePostBlocks', () => {2131 it('should do nothing with no blocks', () => {2132 const blocks = [];2133 const posts = {};2134 const nextBlocks = reducers.mergePostBlocks(blocks, posts);2135 expect(nextBlocks).toBe(blocks);2136 });2137 it('should do nothing with only one block', () => {2138 const blocks = [2139 {order: ['a'], recent: false},2140 ];2141 const posts = {2142 a: {create_at: 1000},2143 };2144 const nextBlocks = reducers.mergePostBlocks(blocks, posts);2145 expect(nextBlocks).toBe(blocks);2146 });2147 it('should do nothing with two separate blocks', () => {2148 const blocks = [2149 {order: ['a'], recent: false},2150 {order: ['b'], recent: false},2151 ];2152 const posts = {2153 a: {create_at: 1000},2154 b: {create_at: 1001},2155 };2156 const nextBlocks = reducers.mergePostBlocks(blocks, posts);2157 expect(nextBlocks).toBe(blocks);2158 });2159 it('should merge two blocks containing exactly the same posts', () => {2160 const blocks = [2161 {order: ['a'], recent: false},2162 {order: ['a'], recent: false},2163 ];2164 const posts = {2165 a: {create_at: 1000},2166 };2167 const nextBlocks = reducers.mergePostBlocks(blocks, posts);2168 expect(nextBlocks).not.toBe(blocks);2169 expect(nextBlocks).toEqual([2170 {order: ['a'], recent: false},2171 ]);2172 });2173 it('should merge two blocks containing overlapping posts', () => {2174 const blocks = [2175 {order: ['a', 'b', 'c'], recent: false},2176 {order: ['b', 'c', 'd'], recent: false},2177 ];2178 const posts = {2179 a: {create_at: 1003},2180 b: {create_at: 1002},2181 c: {create_at: 1001},2182 d: {create_at: 1000},2183 };2184 const nextBlocks = reducers.mergePostBlocks(blocks, posts);2185 expect(nextBlocks).not.toBe(blocks);2186 expect(nextBlocks).toEqual([2187 {order: ['a', 'b', 'c', 'd'], recent: false},2188 ]);2189 });2190 it('should merge more than two blocks containing overlapping posts', () => {2191 const blocks = [2192 {order: ['d', 'e'], recent: false},2193 {order: ['a', 'b'], recent: false},2194 {order: ['c', 'd'], recent: false},2195 {order: ['b', 'c'], recent: false},2196 ];2197 const posts = {2198 a: {create_at: 1004},2199 b: {create_at: 1003},2200 c: {create_at: 1002},2201 d: {create_at: 1001},2202 e: {create_at: 1000},2203 };2204 const nextBlocks = reducers.mergePostBlocks(blocks, posts);2205 expect(nextBlocks).not.toBe(blocks);2206 expect(nextBlocks).toEqual([2207 {order: ['a', 'b', 'c', 'd', 'e'], recent: false},2208 ]);2209 });2210 it('should not affect blocks that are not merged', () => {2211 const blocks = [2212 {order: ['a', 'b'], recent: false},2213 {order: ['b', 'c'], recent: false},2214 {order: ['d', 'e'], recent: false},2215 ];2216 const posts = {2217 a: {create_at: 1004},2218 b: {create_at: 1003},2219 c: {create_at: 1002},2220 d: {create_at: 1001},2221 e: {create_at: 1000},2222 };2223 const nextBlocks = reducers.mergePostBlocks(blocks, posts);2224 expect(nextBlocks).not.toBe(blocks);2225 expect(nextBlocks[1]).toBe(blocks[2]);2226 expect(nextBlocks).toEqual([2227 {order: ['a', 'b', 'c'], recent: false},2228 {order: ['d', 'e'], recent: false},2229 ]);2230 });2231 it('should keep merged blocks marked as recent', () => {2232 const blocks = [2233 {order: ['a', 'b'], recent: true},2234 {order: ['b', 'c'], recent: false},2235 ];2236 const posts = {2237 a: {create_at: 1002},2238 b: {create_at: 1001},2239 c: {create_at: 1000},2240 };2241 const nextBlocks = reducers.mergePostBlocks(blocks, posts);2242 expect(nextBlocks).not.toBe(blocks);2243 expect(nextBlocks).toEqual([2244 {order: ['a', 'b', 'c'], recent: true},2245 ]);2246 });2247 it('should keep merged blocks marked as oldest', () => {2248 const blocks = [2249 {order: ['a', 'b'], oldest: true},2250 {order: ['b', 'c'], oldest: false},2251 ];2252 const posts = {2253 a: {create_at: 1002},2254 b: {create_at: 1001},2255 c: {create_at: 1000},2256 };2257 const nextBlocks = reducers.mergePostBlocks(blocks, posts);2258 expect(nextBlocks).not.toBe(blocks);2259 expect(nextBlocks).toEqual([2260 {order: ['a', 'b', 'c'], oldest: true},2261 ]);2262 });2263 it('should remove empty blocks', () => {2264 const blocks = [2265 {order: ['a', 'b'], recent: true},2266 {order: [], recent: false},2267 ];2268 const posts = {2269 a: {create_at: 1002},2270 b: {create_at: 1001},2271 c: {create_at: 1000},2272 };2273 const nextBlocks = reducers.mergePostBlocks(blocks, posts);2274 expect(nextBlocks).not.toBe(blocks);2275 expect(nextBlocks[0]).toBe(blocks[0]);2276 expect(nextBlocks).toEqual([2277 {order: ['a', 'b'], recent: true},2278 ]);2279 });2280});2281describe('mergePostOrder', () => {2282 const tests = [2283 {2284 name: 'empty arrays',2285 left: [],2286 right: [],2287 expected: [],2288 },2289 {2290 name: 'empty left array',2291 left: [],2292 right: ['c', 'd'],2293 expected: ['c', 'd'],2294 },2295 {2296 name: 'empty right array',2297 left: ['a', 'b'],2298 right: [],2299 expected: ['a', 'b'],2300 },2301 {2302 name: 'distinct arrays',2303 left: ['a', 'b'],2304 right: ['c', 'd'],2305 expected: ['a', 'b', 'c', 'd'],2306 },2307 {2308 name: 'overlapping arrays',2309 left: ['a', 'b', 'c', 'd'],2310 right: ['c', 'd', 'e', 'f'],2311 expected: ['a', 'b', 'c', 'd', 'e', 'f'],2312 },2313 {2314 name: 'left array is start of right array',2315 left: ['a', 'b'],2316 right: ['a', 'b', 'c', 'd'],2317 expected: ['a', 'b', 'c', 'd'],2318 },2319 {2320 name: 'right array is end of left array',2321 left: ['a', 'b', 'c', 'd'],2322 right: ['c', 'd'],2323 expected: ['a', 'b', 'c', 'd'],2324 },2325 {2326 name: 'left array contains right array',2327 left: ['a', 'b', 'c', 'd'],2328 right: ['b', 'c'],2329 expected: ['a', 'b', 'c', 'd'],2330 },2331 {2332 name: 'items in second array missing from first',2333 left: ['a', 'c'],2334 right: ['b', 'd', 'e', 'f'],2335 expected: ['a', 'b', 'c', 'd', 'e', 'f'],2336 },2337 ];2338 const posts = {2339 a: {create_at: 10000},2340 b: {create_at: 9000},2341 c: {create_at: 8000},2342 d: {create_at: 7000},2343 e: {create_at: 6000},2344 f: {create_at: 5000},2345 };2346 for (const test of tests) {2347 it(test.name, () => {2348 const left = [...test.left];2349 const right = [...test.right];2350 const actual = reducers.mergePostOrder(left, right, posts);2351 expect(actual).toEqual(test.expected);2352 // Arguments shouldn't be mutated2353 expect(left).toEqual(test.left);2354 expect(right).toEqual(test.right);2355 });2356 }2357});2358describe('postsInThread', () => {2359 for (const actionType of [2360 PostTypes.RECEIVED_POST,2361 PostTypes.RECEIVED_NEW_POST,2362 ]) {2363 describe(`receiving a single post (${actionType})`, () => {2364 it('should replace a previously pending comment', () => {2365 const state = deepFreeze({2366 root1: ['comment1', 'pending', 'comment2'],2367 });2368 const nextState = reducers.postsInThread(state, {2369 type: actionType,2370 data: {id: 'comment3', root_id: 'root1', pending_post_id: 'pending'},2371 });2372 expect(nextState).not.toBe(state);2373 expect(nextState).toEqual({2374 root1: ['comment1', 'comment2', 'comment3'],2375 });2376 });2377 it('should do nothing for a pending comment that was already removed', () => {2378 const state = deepFreeze({2379 root1: ['comment1', 'comment2'],2380 });2381 const nextState = reducers.postsInThread(state, {2382 type: actionType,2383 data: {id: 'comment2', root_id: 'root1', pending_post_id: 'pending'},2384 });2385 expect(nextState).toBe(state);2386 expect(nextState).toEqual({2387 root1: ['comment1', 'comment2'],2388 });2389 });2390 it('should store a comment that was not previously pending', () => {2391 const state = deepFreeze({2392 root1: ['comment1', 'comment2'],2393 });2394 const nextState = reducers.postsInThread(state, {2395 type: actionType,2396 data: {id: 'comment3', root_id: 'root1'},2397 });2398 expect(nextState).not.toBe(state);2399 expect(nextState).toEqual({2400 root1: ['comment1', 'comment2', 'comment3'],2401 });2402 });2403 it('should store a comment without other comments loaded for the thread', () => {2404 const state = deepFreeze({});2405 const nextState = reducers.postsInThread(state, {2406 type: actionType,2407 data: {id: 'comment1', root_id: 'root1'},2408 });2409 expect(nextState).not.toBe(state);2410 expect(nextState).toEqual({2411 root1: ['comment1'],2412 });2413 });2414 it('should do nothing for a non-comment post', () => {2415 const state = deepFreeze({2416 root1: ['comment1'],2417 });2418 const nextState = reducers.postsInThread(state, {2419 type: actionType,2420 data: {id: 'root2'},2421 });2422 expect(nextState).toBe(state);2423 expect(nextState.root1).toBe(state.root1);2424 expect(nextState).toEqual({2425 root1: ['comment1'],2426 });2427 });2428 it('should do nothing for a duplicate post', () => {2429 const state = deepFreeze({2430 root1: ['comment1', 'comment2'],2431 });2432 const nextState = reducers.postsInThread(state, {2433 type: actionType,2434 data: {id: 'comment1'},2435 });2436 expect(nextState).toBe(state);2437 expect(nextState).toEqual({2438 root1: ['comment1', 'comment2'],2439 });2440 });2441 });2442 }2443 for (const actionType of [2444 PostTypes.RECEIVED_POSTS_AFTER,2445 PostTypes.RECEIVED_POSTS_BEFORE,2446 PostTypes.RECEIVED_POSTS_IN_CHANNEL,2447 PostTypes.RECEIVED_POSTS_SINCE,2448 ]) {2449 describe(`receiving posts in the channel (${actionType})`, () => {2450 it('should save comments without in the correct threads without sorting', () => {2451 const state = deepFreeze({2452 root1: ['comment1'],2453 });2454 const posts = {2455 comment2: {id: 'comment2', root_id: 'root1'},2456 comment3: {id: 'comment3', root_id: 'root2'},2457 comment4: {id: 'comment4', root_id: 'root1'},2458 };2459 const nextState = reducers.postsInThread(state, {2460 type: actionType,2461 data: {2462 order: [],2463 posts,2464 },2465 });2466 expect(nextState).not.toBe(state);2467 expect(nextState).toEqual({2468 root1: ['comment1', 'comment2', 'comment4'],2469 root2: ['comment3'],2470 });2471 });2472 it('should not save not-comment posts', () => {2473 const state = deepFreeze({2474 root1: ['comment1'],2475 });2476 const posts = {2477 comment2: {id: 'comment2', root_id: 'root1'},2478 root2: {id: 'root2'},2479 comment3: {id: 'comment3', root_id: 'root2'},2480 };2481 const nextState = reducers.postsInThread(state, {2482 type: actionType,2483 data: {2484 order: [],2485 posts,2486 },2487 });2488 expect(nextState).not.toBe(state);2489 expect(nextState).toEqual({2490 root1: ['comment1', 'comment2'],2491 root2: ['comment3'],2492 });2493 });2494 it('should not save duplicate posts', () => {2495 const state = deepFreeze({2496 root1: ['comment1'],2497 });2498 const posts = {2499 comment1: {id: 'comment2', root_id: 'root1'},2500 comment2: {id: 'comment2', root_id: 'root1'},2501 };2502 const nextState = reducers.postsInThread(state, {2503 type: actionType,2504 data: {2505 order: [],2506 posts,2507 },2508 });2509 expect(nextState).not.toBe(state);2510 expect(nextState).toEqual({2511 root1: ['comment1', 'comment2'],2512 });2513 });2514 it('should do nothing when receiving no posts', () => {2515 const state = deepFreeze({2516 root1: ['comment1'],2517 });2518 const posts = {};2519 const nextState = reducers.postsInThread(state, {2520 type: actionType,2521 data: {2522 order: [],2523 posts,2524 },2525 });2526 expect(nextState).toBe(state);2527 expect(nextState).toEqual({2528 root1: ['comment1'],2529 });2530 });2531 it('should do nothing when receiving no comments', () => {2532 const state = deepFreeze({2533 root1: ['comment1'],2534 });2535 const posts = {2536 root2: {id: 'root2'},2537 };2538 const nextState = reducers.postsInThread(state, {2539 type: actionType,2540 data: {2541 order: [],2542 posts,2543 },2544 });2545 expect(nextState).toBe(state);2546 expect(nextState).toEqual({2547 root1: ['comment1'],2548 });2549 });2550 });2551 }2552 describe('receiving posts in a thread', () => {2553 it('should save comments without sorting', () => {2554 const state = deepFreeze({2555 root1: ['comment1'],2556 });2557 const posts = {2558 comment2: {id: 'comment2', root_id: 'root1'},2559 comment3: {id: 'comment3', root_id: 'root1'},2560 };2561 const nextState = reducers.postsInThread(state, {2562 type: PostTypes.RECEIVED_POSTS_IN_THREAD,2563 data: {2564 order: [],2565 posts,2566 },2567 rootId: 'root1',2568 });2569 expect(nextState).not.toBe(state);2570 expect(nextState).toEqual({2571 root1: ['comment1', 'comment2', 'comment3'],2572 });2573 });2574 it('should not save the root post', () => {2575 const state = deepFreeze({2576 root1: ['comment1'],2577 });2578 const posts = {2579 root2: {id: 'root2'},2580 comment2: {id: 'comment2', root_id: 'root2'},2581 comment3: {id: 'comment3', root_id: 'root2'},2582 };2583 const nextState = reducers.postsInThread(state, {2584 type: PostTypes.RECEIVED_POSTS_IN_THREAD,2585 data: {2586 order: [],2587 posts,2588 },2589 rootId: 'root2',2590 });2591 expect(nextState).not.toBe(state);2592 expect(nextState.root1).toBe(state.root1);2593 expect(nextState).toEqual({2594 root1: ['comment1'],2595 root2: ['comment2', 'comment3'],2596 });2597 });2598 it('should not save duplicate posts', () => {2599 const state = deepFreeze({2600 root1: ['comment1'],2601 });2602 const posts = {2603 comment1: {id: 'comment1', root_id: 'root1'},2604 comment2: {id: 'comment2', root_id: 'root1'},2605 };2606 const nextState = reducers.postsInThread(state, {2607 type: PostTypes.RECEIVED_POSTS_IN_THREAD,2608 data: {2609 order: [],2610 posts,2611 },2612 rootId: 'root1',2613 });2614 expect(nextState).not.toBe(state);2615 expect(nextState).toEqual({2616 root1: ['comment1', 'comment2'],2617 });2618 });2619 it('should do nothing when receiving no posts', () => {2620 const state = deepFreeze({2621 root1: ['comment1'],2622 });2623 const posts = {};2624 const nextState = reducers.postsInThread(state, {2625 type: PostTypes.RECEIVED_POSTS_IN_THREAD,2626 data: {2627 order: [],2628 posts,2629 },2630 rootId: 'root2',2631 });2632 expect(nextState).toBe(state);2633 expect(nextState).toEqual({2634 root1: ['comment1'],2635 });2636 });2637 });2638 describe('deleting a post', () => {2639 it('should remove the thread when deleting the root post', () => {2640 const state = deepFreeze({2641 root1: ['comment1', 'comment2'],2642 root2: ['comment3'],2643 });2644 const nextState = reducers.postsInThread(state, {2645 type: PostTypes.POST_DELETED,2646 data: {id: 'root1'},2647 });2648 expect(nextState).not.toBe(state);2649 expect(nextState.root2).toBe(state.root2);2650 expect(nextState).toEqual({2651 root2: ['comment3'],2652 });2653 });2654 it('should do nothing when deleting a comment', () => {2655 const state = deepFreeze({2656 root1: ['comment1', 'comment2'],2657 });2658 const nextState = reducers.postsInThread(state, {2659 type: PostTypes.POST_DELETED,2660 data: {id: 'comment1'},2661 });2662 expect(nextState).toBe(state);2663 expect(nextState).toEqual({2664 root1: ['comment1', 'comment2'],2665 });2666 });2667 it('should do nothing if deleting a post without comments', () => {2668 const state = deepFreeze({2669 root1: ['comment1', 'comment2'],2670 });2671 const nextState = reducers.postsInThread(state, {2672 type: PostTypes.POST_DELETED,2673 data: {id: 'root2'},2674 });2675 expect(nextState).toBe(state);2676 expect(nextState).toEqual({2677 root1: ['comment1', 'comment2'],2678 });2679 });2680 });2681 describe('removing a post', () => {2682 it('should remove the thread when removing the root post', () => {2683 const state = deepFreeze({2684 root1: ['comment1', 'comment2'],2685 root2: ['comment3'],2686 });2687 const nextState = reducers.postsInThread(state, {2688 type: PostTypes.POST_REMOVED,2689 data: {id: 'root1'},2690 });2691 expect(nextState).not.toBe(state);2692 expect(nextState.root2).toBe(state.root2);2693 expect(nextState).toEqual({2694 root2: ['comment3'],2695 });2696 });2697 it('should remove an entry from the thread when removing a comment', () => {2698 const state = deepFreeze({2699 root1: ['comment1', 'comment2'],2700 root2: ['comment3'],2701 });2702 const nextState = reducers.postsInThread(state, {2703 type: PostTypes.POST_REMOVED,2704 data: {id: 'comment1', root_id: 'root1'},2705 });2706 expect(nextState).not.toBe(state);2707 expect(nextState.root2).toBe(state.root2);2708 expect(nextState).toEqual({2709 root1: ['comment2'],2710 root2: ['comment3'],2711 });2712 });2713 it('should do nothing if removing a thread that has not been loaded', () => {2714 const state = deepFreeze({2715 root1: ['comment1', 'comment2'],2716 });2717 const nextState = reducers.postsInThread(state, {2718 type: PostTypes.POST_REMOVED,2719 data: {id: 'root2'},2720 });2721 expect(nextState).toBe(state);2722 expect(nextState).toEqual({2723 root1: ['comment1', 'comment2'],2724 });2725 });2726 });2727 for (const actionType of [2728 ChannelTypes.RECEIVED_CHANNEL_DELETED,2729 ChannelTypes.DELETE_CHANNEL_SUCCESS,2730 ChannelTypes.LEAVE_CHANNEL,2731 ]) {2732 describe(`when a channel is deleted (${actionType})`, () => {2733 it('should remove any threads in that channel', () => {2734 const state = deepFreeze({2735 root1: ['comment1', 'comment2'],2736 root2: ['comment3'],2737 root3: ['comment4'],2738 });2739 const prevPosts = {2740 root1: {id: 'root1', channel_id: 'channel1'},2741 comment1: {id: 'comment1', channel_id: 'channel1', root_id: 'root1'},2742 comment2: {id: 'comment2', channel_id: 'channel1', root_id: 'root1'},2743 root2: {id: 'root2', channel_id: 'channel2'},2744 comment3: {id: 'comment3', channel_id: 'channel2', root_id: 'root2'},2745 root3: {id: 'root3', channel_id: 'channel1'},2746 comment4: {id: 'comment3', channel_id: 'channel1', root_id: 'root3'},2747 };2748 const nextState = reducers.postsInThread(state, {2749 type: actionType,2750 data: {2751 id: 'channel1',2752 viewArchivedChannels: false,2753 },2754 }, prevPosts);2755 expect(nextState).not.toBe(state);2756 expect(nextState.root2).toBe(state.root2);2757 expect(nextState).toEqual({2758 root2: ['comment3'],2759 });2760 });2761 it('should do nothing if no threads in that channel are loaded', () => {2762 const state = deepFreeze({2763 root1: ['comment1', 'comment2'],2764 });2765 const prevPosts = {2766 root1: {id: 'root1', channel_id: 'channel1'},2767 comment1: {id: 'comment1', channel_id: 'channel1', root_id: 'root1'},2768 comment2: {id: 'comment2', channel_id: 'channel1', root_id: 'root1'},2769 };2770 const nextState = reducers.postsInThread(state, {2771 type: actionType,2772 data: {2773 id: 'channel2',2774 viewArchivedChannels: false,2775 },2776 }, prevPosts);2777 expect(nextState).toBe(state);2778 expect(nextState).toEqual({2779 root1: ['comment1', 'comment2'],2780 });2781 });2782 it('should not remove any posts with viewArchivedChannels enabled', () => {2783 const state = deepFreeze({2784 root1: ['comment1', 'comment2'],2785 root2: ['comment3'],2786 });2787 const prevPosts = {2788 root1: {id: 'root1', channel_id: 'channel1'},2789 comment1: {id: 'comment1', channel_id: 'channel1', root_id: 'root1'},2790 comment2: {id: 'comment2', channel_id: 'channel1', root_id: 'root1'},2791 root2: {id: 'root2', channel_id: 'channel2'},2792 comment3: {id: 'comment3', channel_id: 'channel2', root_id: 'root2'},2793 };2794 const nextState = reducers.postsInThread(state, {2795 type: actionType,2796 data: {2797 id: 'channel1',2798 viewArchivedChannels: true,2799 },2800 }, prevPosts);2801 expect(nextState).toBe(state);2802 expect(nextState).toEqual({2803 root1: ['comment1', 'comment2'],2804 root2: ['comment3'],2805 });2806 });2807 it('should not error if a post is missing from prevPosts', () => {2808 const state = deepFreeze({2809 root1: ['comment1'],2810 });2811 const prevPosts = {2812 comment1: {id: 'comment1', channel_id: 'channel1', root_id: 'root1'},2813 };2814 const nextState = reducers.postsInThread(state, {2815 type: actionType,2816 data: {2817 id: 'channel1',2818 viewArchivedChannels: false,2819 },2820 }, prevPosts);2821 expect(nextState).toBe(state);2822 });2823 });2824 }2825});2826describe('removeUnneededMetadata', () => {2827 it('without metadata', () => {2828 const post = deepFreeze({2829 id: 'post',2830 });2831 const nextPost = reducers.removeUnneededMetadata(post);2832 assert.equal(nextPost, post);2833 });2834 it('with empty metadata', () => {2835 const post = deepFreeze({2836 id: 'post',2837 metadata: {},2838 });2839 const nextPost = reducers.removeUnneededMetadata(post);2840 assert.equal(nextPost, post);2841 });2842 it('should remove emojis', () => {2843 const post = deepFreeze({2844 id: 'post',2845 metadata: {2846 emojis: [{name: 'emoji'}],2847 },2848 });2849 const nextPost = reducers.removeUnneededMetadata(post);2850 assert.notEqual(nextPost, post);2851 assert.deepEqual(nextPost, {2852 id: 'post',2853 metadata: {},2854 });2855 });2856 it('should remove files', () => {2857 const post = deepFreeze({2858 id: 'post',2859 metadata: {2860 files: [{id: 'file', post_id: 'post'}],2861 },2862 });2863 const nextPost = reducers.removeUnneededMetadata(post);2864 assert.notEqual(nextPost, post);2865 assert.deepEqual(nextPost, {2866 id: 'post',2867 metadata: {},2868 });2869 });2870 it('should remove reactions', () => {2871 const post = deepFreeze({2872 id: 'post',2873 metadata: {2874 reactions: [2875 {user_id: 'abcd', emoji_name: '+1'},2876 {user_id: 'efgh', emoji_name: '+1'},2877 {user_id: 'abcd', emoji_name: '-1'},2878 ],2879 },2880 });2881 const nextPost = reducers.removeUnneededMetadata(post);2882 assert.notEqual(nextPost, post);2883 assert.deepEqual(nextPost, {2884 id: 'post',2885 metadata: {},2886 });2887 });2888 it('should remove OpenGraph data', () => {2889 const post = deepFreeze({2890 id: 'post',2891 metadata: {2892 embeds: [{2893 type: 'opengraph',2894 url: 'https://example.com',2895 data: {2896 url: 'https://example.com',2897 images: [{2898 url: 'https://example.com/logo.png',2899 width: 100,2900 height: 100,2901 }],2902 },2903 }],2904 },2905 });2906 const nextPost = reducers.removeUnneededMetadata(post);2907 assert.notEqual(nextPost, post);2908 assert.deepEqual(nextPost, {2909 id: 'post',2910 metadata: {2911 embeds: [{2912 type: 'opengraph',2913 url: 'https://example.com',2914 }],2915 },2916 });2917 });2918 it('should not affect non-OpenGraph embeds', () => {2919 const post = deepFreeze({2920 id: 'post',2921 metadata: {2922 embeds: [2923 {type: 'image', url: 'https://example.com/image'},2924 {type: 'message_attachment'},2925 ],2926 },2927 props: {2928 attachments: [2929 {text: 'This is an attachment'},2930 ],2931 },2932 });2933 const nextPost = reducers.removeUnneededMetadata(post);2934 assert.equal(nextPost, post);2935 });2936});2937describe('reactions', () => {2938 for (const actionType of [2939 PostTypes.RECEIVED_NEW_POST,2940 PostTypes.RECEIVED_POST,2941 ]) {2942 describe(`single post received (${actionType})`, () => {2943 it('no post metadata', () => {2944 const state = deepFreeze({});2945 const action = {2946 type: actionType,2947 data: {2948 id: 'post',2949 },2950 };2951 const nextState = reducers.reactions(state, action);2952 assert.equal(nextState, state);2953 });2954 it('no reactions in post metadata', () => {2955 const state = deepFreeze({});2956 const action = {2957 type: actionType,2958 data: {2959 id: 'post',2960 metadata: {reactions: []},2961 },2962 };2963 const nextState = reducers.reactions(state, action);2964 assert.notEqual(nextState, state);2965 assert.deepEqual(nextState, {2966 post: {},2967 });2968 });2969 it('should not clobber reactions when metadata empty', () => {2970 const state = deepFreeze({post: {name: 'smiley', post_id: 'post'}});2971 const action = {2972 type: actionType,2973 data: {2974 id: 'post',2975 metadata: {},2976 },2977 };2978 const nextState = reducers.reactions(state, action);2979 assert.deepEqual(nextState, {2980 post: {name: 'smiley', post_id: 'post'},2981 });2982 });2983 it('should save reactions', () => {2984 const state = deepFreeze({});2985 const action = {2986 type: actionType,2987 data: {2988 id: 'post',2989 metadata: {2990 reactions: [2991 {user_id: 'abcd', emoji_name: '+1'},2992 {user_id: 'efgh', emoji_name: '+1'},2993 {user_id: 'abcd', emoji_name: '-1'},2994 ],2995 },2996 },2997 };2998 const nextState = reducers.reactions(state, action);2999 assert.notEqual(nextState, state);3000 assert.deepEqual(nextState, {3001 post: {3002 'abcd-+1': {user_id: 'abcd', emoji_name: '+1'},3003 'efgh-+1': {user_id: 'efgh', emoji_name: '+1'},3004 'abcd--1': {user_id: 'abcd', emoji_name: '-1'},3005 },3006 });3007 });3008 it('should not save reaction for a deleted post', () => {3009 const state = deepFreeze({});3010 const action = {3011 type: actionType,3012 data: {3013 id: 'post',3014 delete_at: '1571366424287',3015 },3016 };3017 const nextState = reducers.reactions(state, action);3018 assert.equal(nextState, state);3019 });3020 });3021 }3022 describe('receiving multiple posts', () => {3023 it('no post metadata', () => {3024 const state = deepFreeze({});3025 const action = {3026 type: PostTypes.RECEIVED_POSTS,3027 data: {3028 posts: {3029 post: {3030 id: 'post',3031 },3032 },3033 },3034 };3035 const nextState = reducers.reactions(state, action);3036 assert.equal(nextState, state);3037 });3038 it('no reactions in post metadata', () => {3039 const state = deepFreeze({});3040 const action = {3041 type: PostTypes.RECEIVED_POSTS,3042 data: {3043 posts: {3044 post: {3045 id: 'post',3046 metadata: {reactions: []},3047 },3048 },3049 },3050 };3051 const nextState = reducers.reactions(state, action);3052 assert.notEqual(nextState, state);3053 assert.deepEqual(nextState, {3054 post: {},3055 });3056 });3057 it('should save reactions', () => {3058 const state = deepFreeze({});3059 const action = {3060 type: PostTypes.RECEIVED_POSTS,3061 data: {3062 posts: {3063 post: {3064 id: 'post',3065 metadata: {3066 reactions: [3067 {user_id: 'abcd', emoji_name: '+1'},3068 {user_id: 'efgh', emoji_name: '+1'},3069 {user_id: 'abcd', emoji_name: '-1'},3070 ],3071 },3072 },3073 },3074 },3075 };3076 const nextState = reducers.reactions(state, action);3077 assert.notEqual(nextState, state);3078 assert.deepEqual(nextState, {3079 post: {3080 'abcd-+1': {user_id: 'abcd', emoji_name: '+1'},3081 'efgh-+1': {user_id: 'efgh', emoji_name: '+1'},3082 'abcd--1': {user_id: 'abcd', emoji_name: '-1'},3083 },3084 });3085 });3086 it('should save reactions for multiple posts', () => {3087 const state = deepFreeze({});3088 const action = {3089 type: PostTypes.RECEIVED_POSTS,3090 data: {3091 posts: {3092 post1: {3093 id: 'post1',3094 metadata: {3095 reactions: [3096 {user_id: 'abcd', emoji_name: '+1'},3097 ],3098 },3099 },3100 post2: {3101 id: 'post2',3102 metadata: {3103 reactions: [3104 {user_id: 'abcd', emoji_name: '-1'},3105 ],3106 },3107 },3108 },3109 },3110 };3111 const nextState = reducers.reactions(state, action);3112 assert.notEqual(nextState, state);3113 assert.deepEqual(nextState, {3114 post1: {3115 'abcd-+1': {user_id: 'abcd', emoji_name: '+1'},3116 },3117 post2: {3118 'abcd--1': {user_id: 'abcd', emoji_name: '-1'},3119 },3120 });3121 });3122 it('should save reactions for multiple posts except deleted posts', () => {3123 const state = deepFreeze({});3124 const action = {3125 type: PostTypes.RECEIVED_POSTS,3126 data: {3127 posts: {3128 post1: {3129 id: 'post1',3130 metadata: {3131 reactions: [3132 {user_id: 'abcd', emoji_name: '+1'},3133 ],3134 },3135 },3136 post2: {3137 id: 'post2',3138 delete_at: '1571366424287',3139 metadata: {3140 reactions: [3141 {user_id: 'abcd', emoji_name: '-1'},3142 ],3143 },3144 },3145 },3146 },3147 };3148 const nextState = reducers.reactions(state, action);3149 assert.notEqual(nextState, state);3150 assert.deepEqual(nextState, {3151 post1: {3152 'abcd-+1': {user_id: 'abcd', emoji_name: '+1'},3153 },3154 });3155 });3156 });3157});3158describe('opengraph', () => {3159 for (const actionType of [3160 PostTypes.RECEIVED_NEW_POST,3161 PostTypes.RECEIVED_POST,3162 ]) {3163 describe(`single post received (${actionType})`, () => {3164 it('no post metadata', () => {3165 const state = deepFreeze({});3166 const action = {3167 type: actionType,3168 data: {3169 id: 'post',3170 },3171 };3172 const nextState = reducers.openGraph(state, action);3173 assert.equal(nextState, state);3174 });3175 it('no embeds in post metadata', () => {3176 const state = deepFreeze({});3177 const action = {3178 type: actionType,3179 data: {3180 id: 'post',3181 metadata: {},3182 },3183 };3184 const nextState = reducers.openGraph(state, action);3185 assert.equal(nextState, state);3186 });3187 it('other types of embeds in post metadata', () => {3188 const state = deepFreeze({});3189 const action = {3190 type: actionType,3191 data: {3192 id: 'post',3193 metadata: {3194 embeds: [{3195 type: 'image',3196 url: 'https://example.com/image.png',3197 }, {3198 type: 'message_attachment',3199 }],3200 },3201 },3202 };3203 const nextState = reducers.openGraph(state, action);3204 assert.equal(nextState, state);3205 });3206 it('should save opengraph data', () => {3207 const state = deepFreeze({});3208 const action = {3209 type: actionType,3210 data: {3211 id: 'post',3212 metadata: {3213 embeds: [{3214 type: 'opengraph',3215 url: 'https://example.com',3216 data: {3217 title: 'Example',3218 description: 'Example description',3219 },3220 }],3221 },3222 },3223 };3224 const nextState = reducers.openGraph(state, action);3225 assert.notEqual(nextState, state);3226 assert.deepEqual(nextState, {3227 post: {'https://example.com': action.data.metadata.embeds[0].data},3228 });3229 });3230 });3231 }3232 describe('receiving multiple posts', () => {3233 it('no post metadata', () => {3234 const state = deepFreeze({});3235 const action = {3236 type: PostTypes.RECEIVED_POSTS,3237 data: {3238 posts: {3239 post: {3240 id: 'post',3241 },3242 },3243 },3244 };3245 const nextState = reducers.openGraph(state, action);3246 assert.equal(nextState, state);3247 });3248 it('no embeds in post metadata', () => {3249 const state = deepFreeze({});3250 const action = {3251 type: PostTypes.RECEIVED_POSTS,3252 data: {3253 posts: {3254 post: {3255 id: 'post',3256 metadata: {},3257 },3258 },3259 },3260 };3261 const nextState = reducers.openGraph(state, action);3262 assert.equal(nextState, state);3263 });3264 it('other types of embeds in post metadata', () => {3265 const state = deepFreeze({});3266 const action = {3267 type: PostTypes.RECEIVED_POSTS,3268 data: {3269 posts: {3270 post: {3271 id: 'post',3272 metadata: {3273 embeds: [{3274 type: 'image',3275 url: 'https://example.com/image.png',3276 }, {3277 type: 'message_attachment',3278 }],3279 },3280 },3281 },3282 },3283 };3284 const nextState = reducers.openGraph(state, action);3285 assert.equal(nextState, state);3286 });3287 it('should save opengraph data', () => {3288 const state = deepFreeze({});3289 const action = {3290 type: PostTypes.RECEIVED_POSTS,3291 data: {3292 posts: {3293 post1: {3294 id: 'post1',3295 metadata: {3296 embeds: [{3297 type: 'opengraph',3298 url: 'https://example.com',3299 data: {3300 title: 'Example',3301 description: 'Example description',3302 },3303 }],3304 },3305 },3306 },3307 },3308 };3309 const nextState = reducers.openGraph(state, action);3310 assert.notEqual(nextState, state);3311 assert.deepEqual(nextState, {3312 post1: {'https://example.com': action.data.posts.post1.metadata.embeds[0].data},3313 });3314 });3315 it('should save reactions for multiple posts', () => {3316 const state = deepFreeze({});3317 const action = {3318 type: PostTypes.RECEIVED_POSTS,3319 data: {3320 posts: {3321 post1: {3322 id: 'post1',3323 metadata: {3324 embeds: [{3325 type: 'opengraph',3326 url: 'https://example.com',3327 data: {3328 title: 'Example',3329 description: 'Example description',3330 },3331 }],3332 },3333 },3334 post2: {3335 id: 'post2',3336 metadata: {3337 embeds: [{3338 type: 'opengraph',3339 url: 'https://google.ca',3340 data: {3341 title: 'Google',3342 description: 'Something about search',3343 },3344 }],3345 },3346 },3347 },3348 },3349 };3350 const nextState = reducers.openGraph(state, action);3351 assert.notEqual(nextState, state);3352 assert.deepEqual(nextState, {3353 post1: {'https://example.com': action.data.posts.post1.metadata.embeds[0].data},3354 post2: {'https://google.ca': action.data.posts.post2.metadata.embeds[0].data},3355 });3356 });3357 });3358});3359describe('expandedURLs', () => {3360 it('should store the URLs on REDIRECT_LOCATION_SUCCESS', () => {3361 const state = deepFreeze({});3362 const action = {3363 type: GeneralTypes.REDIRECT_LOCATION_SUCCESS,3364 data: {3365 url: 'a',3366 location: 'b',3367 },3368 };3369 const nextState = reducers.expandedURLs(state, action);3370 assert.notEqual(state, nextState);3371 assert.deepEqual(nextState, {3372 a: 'b',3373 });3374 });3375 it('should store the non-expanded URL on REDIRECT_LOCATION_FAILURE', () => {3376 const state = deepFreeze({});3377 const action = {3378 type: GeneralTypes.REDIRECT_LOCATION_FAILURE,3379 data: {3380 url: 'b',3381 },3382 };3383 const nextState = reducers.expandedURLs(state, action);3384 assert.notEqual(state, nextState);3385 assert.deepEqual(nextState, {3386 b: 'b',3387 });3388 });3389});3390describe('removeNonRecentEmptyPostBlocks', () => {3391 it('should filter empty blocks', () => {3392 const blocks = [{3393 order: [],3394 recent: false,3395 }, {3396 order: ['1', '2'],3397 recent: false,3398 }];3399 const filteredBlocks = reducers.removeNonRecentEmptyPostBlocks(blocks);3400 assert.deepEqual(filteredBlocks, [{3401 order: ['1', '2'],3402 recent: false,3403 }]);3404 });3405 it('should not filter empty recent block', () => {3406 const blocks = [{3407 order: [],3408 recent: true,3409 }, {3410 order: ['1', '2'],3411 recent: false,3412 }, {3413 order: [],3414 recent: false,3415 }];3416 const filteredBlocks = reducers.removeNonRecentEmptyPostBlocks(blocks);3417 assert.deepEqual(filteredBlocks, [{3418 order: [],3419 recent: true,3420 }, {3421 order: ['1', '2'],3422 recent: false,3423 }]);3424 });3425});3426describe('postsReplies', () => {3427 const initialState = {3428 123: 3,3429 456: 6,3430 789: 9,3431 };3432 describe('received post', () => {3433 const testTable = [3434 {name: 'pending post (no id)', action: PostTypes.RECEIVED_POST, state: {...initialState}, post: {root_id: '123'}, nextState: {...initialState}},3435 {name: 'root post (no root_id)', action: PostTypes.RECEIVED_POST, state: {...initialState}, post: {id: '123'}, nextState: {...initialState}},3436 {name: 'new reply without reply count', action: PostTypes.RECEIVED_POST, state: {...initialState}, post: {id: '123', root_id: '123'}, nextState: {...initialState, 123: 4}},3437 {name: 'new reply with reply count', action: PostTypes.RECEIVED_POST, state: {...initialState}, post: {id: '123', root_id: '123', reply_count: 7}, nextState: {...initialState, 123: 7}},3438 {name: 'pending post (no id) (new post action)', action: PostTypes.RECEIVED_NEW_POST, state: {...initialState}, post: {root_id: '123'}, nextState: {...initialState}},3439 {name: 'root post (no root_id) (new post action)', action: PostTypes.RECEIVED_NEW_POST, state: {...initialState}, post: {id: '123'}, nextState: {...initialState}},3440 {name: 'new reply without reply count (new post action)', action: PostTypes.RECEIVED_NEW_POST, state: {...initialState}, post: {id: '123', root_id: '123'}, nextState: {...initialState, 123: 4}},3441 {name: 'new reply with reply count (new post action)', action: PostTypes.RECEIVED_NEW_POST, state: {...initialState}, post: {id: '123', root_id: '123', reply_count: 7}, nextState: {...initialState, 123: 7}},3442 ];3443 for (const testCase of testTable) {3444 it(testCase.name, () => {3445 const state = deepFreeze(testCase.state);3446 const nextState = reducers.nextPostsReplies(state, {3447 type: testCase.action,3448 data: testCase.post,3449 });3450 expect(nextState).toEqual(testCase.nextState);3451 });3452 }3453 });3454 describe('received posts', () => {3455 const testTable = [3456 {name: 'received empty posts list', action: PostTypes.RECEIVED_POSTS, state: {...initialState}, posts: [], nextState: {...initialState}},3457 {3458 name: 'received posts to existing counters',3459 action: PostTypes.RECEIVED_POSTS,3460 state: {...initialState},3461 posts: [3462 {id: '123', reply_count: 1},3463 {id: '456', reply_count: 8},3464 ],3465 nextState: {...initialState, 123: 1, 456: 8},3466 },3467 {3468 name: 'received replies to existing counters',3469 action: PostTypes.RECEIVED_POSTS,3470 state: {...initialState},3471 posts: [3472 {id: '000', root_id: '123', reply_count: 1},3473 {id: '111', root_id: '456', reply_count: 8},3474 ],3475 nextState: {...initialState, 123: 1, 456: 8},3476 },3477 {3478 name: 'received posts to new counters',3479 action: PostTypes.RECEIVED_POSTS,3480 state: {...initialState},3481 posts: [3482 {id: '321', reply_count: 1},3483 {id: '654', reply_count: 8},3484 ],3485 nextState: {...initialState, 321: 1, 654: 8},3486 },3487 {3488 name: 'received replies to new counters',3489 action: PostTypes.RECEIVED_POSTS,3490 state: {...initialState},3491 posts: [3492 {id: '000', root_id: '321', reply_count: 1},3493 {id: '111', root_id: '654', reply_count: 8},3494 ],3495 nextState: {...initialState, 321: 1, 654: 8},3496 },3497 {3498 name: 'received posts and replies to new and existing counters',3499 action: PostTypes.RECEIVED_POSTS,3500 state: {...initialState},3501 posts: [3502 {id: '000', root_id: '123', reply_count: 4},3503 {id: '111', root_id: '456', reply_count: 7},3504 {id: '000', root_id: '321', reply_count: 1},3505 {id: '111', root_id: '654', reply_count: 8},3506 ],3507 nextState: {...initialState, 123: 4, 456: 7, 321: 1, 654: 8},3508 },3509 ];3510 for (const testCase of testTable) {3511 it(testCase.name, () => {3512 const state = deepFreeze(testCase.state);3513 const nextState = reducers.nextPostsReplies(state, {3514 type: testCase.action,3515 data: {posts: testCase.posts},3516 });3517 expect(nextState).toEqual(testCase.nextState);3518 });3519 }3520 });3521 describe('deleted posts', () => {3522 const testTable = [3523 {name: 'deleted not tracked post', action: PostTypes.POST_DELETED, state: {...initialState}, post: {id: '000', root_id: '111'}, nextState: {...initialState}},3524 {name: 'deleted reply', action: PostTypes.POST_DELETED, state: {...initialState}, post: {id: '000', root_id: '123'}, nextState: {...initialState, 123: 2}},3525 {name: 'deleted root post', action: PostTypes.POST_DELETED, state: {...initialState}, post: {id: '123'}, nextState: {456: 6, 789: 9}},3526 ];3527 for (const testCase of testTable) {3528 it(testCase.name, () => {3529 const state = deepFreeze(testCase.state);3530 const nextState = reducers.nextPostsReplies(state, {3531 type: testCase.action,3532 data: testCase.post,3533 });3534 expect(nextState).toEqual(testCase.nextState);3535 });3536 }3537 });...

Full Screen

Full Screen

channel_categories.test.js

Source:channel_categories.test.js Github

copy

Full Screen

1// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.2// See LICENSE.txt for license information.3import {General, Preferences} from '../../constants';4import {CategoryTypes} from '../../constants/channel_categories';5import {getCurrentChannelId, getMyChannelMemberships} from 'selectors/entities/channels';6import {getConfig} from 'selectors/entities/general';7import {getLastPostPerChannel} from 'selectors/entities/posts';8import {getMyPreferences} from 'selectors/entities/preferences';9import {getCurrentUserId} from 'selectors/entities/users';10import mergeObjects from 'test/merge_objects';11import {isGroupOrDirectChannelVisible} from 'utils/channel_utils';12import {getPreferenceKey} from 'utils/preference_utils';13import * as Selectors from './channel_categories';14describe('makeGetCategoriesForTeam', () => {15 const category1 = {id: 'category1', display_name: 'Category One', type: CategoryTypes.CUSTOM};16 const category2 = {id: 'category2', display_name: 'Category Two', type: CategoryTypes.CUSTOM};17 const state = {18 entities: {19 channelCategories: {20 byId: {21 category1,22 category2,23 },24 orderByTeam: {25 team1: [category2.id, category1.id],26 },27 },28 },29 };30 test('should return categories for team in order', () => {31 const getCategoriesForTeam = Selectors.makeGetCategoriesForTeam();32 expect(getCategoriesForTeam(state, 'team1')).toEqual([33 state.entities.channelCategories.byId.category2,34 state.entities.channelCategories.byId.category1,35 ]);36 });37 test('should memoize properly', () => {38 const getCategoriesForTeam = Selectors.makeGetCategoriesForTeam();39 const result = getCategoriesForTeam(state, 'team1');40 // Repeat calls should return the same array41 expect(getCategoriesForTeam(state, 'team1')).toBe(result);42 // Calls to a difference instance of the selector won't return the same array43 expect(result).not.toBe(Selectors.makeGetCategoriesForTeam()(state, 'team1'));44 // Calls with different arguments won't return the same array45 expect(getCategoriesForTeam(state, 'team2')).not.toBe(result);46 // Calls after different argumetns won't return the same array47 expect(getCategoriesForTeam(state, 'team1')).not.toBe(result);48 });49});50describe('makeGetUnsortedUnfilteredChannels', () => {51 const channel1 = {id: 'channel1', team_id: 'team1', delete_at: 0};52 const channel2 = {id: 'channel2', team_id: 'team1', delete_at: 0};53 const channel3 = {id: 'channel3', team_id: 'team2', delete_at: 0};54 const dmChannel1 = {id: 'dmChannel1', team_id: '', delete_at: 0};55 const gmChannel1 = {id: 'gmChannel1', team_id: '', delete_at: 0};56 const baseState = {57 entities: {58 channels: {59 channels: {60 channel1,61 channel2,62 channel3,63 dmChannel1,64 gmChannel1,65 },66 myMembers: {67 [channel1.id]: {},68 [channel2.id]: {},69 [channel3.id]: {},70 [dmChannel1.id]: {},71 [gmChannel1.id]: {},72 },73 },74 },75 };76 test('should return channels on the team and DMs/GMs', () => {77 const getUnsortedUnfilteredChannels = Selectors.makeGetUnsortedUnfilteredChannels();78 expect(getUnsortedUnfilteredChannels(baseState, 'team1')).toMatchObject([channel1, channel2, dmChannel1, gmChannel1]);79 expect(getUnsortedUnfilteredChannels(baseState, 'team2')).toMatchObject([channel3, dmChannel1, gmChannel1]);80 });81 test('should not return channels which the user is not a member of', () => {82 const channel4 = {id: 'channel4', team_id: 'team1', delete_at: 0};83 const getUnsortedUnfilteredChannels = Selectors.makeGetUnsortedUnfilteredChannels();84 let state = {85 entities: {86 channels: {87 channels: {88 channel4,89 },90 myMembers: {},91 },92 },93 };94 expect(getUnsortedUnfilteredChannels(state, 'team1')).not.toContain(channel4);95 state = {96 entities: {97 channels: {98 channels: {99 channel4,100 },101 myMembers: {102 [channel4.id]: {},103 },104 },105 },106 };107 expect(getUnsortedUnfilteredChannels(state, 'team1')).toContain(channel4);108 });109 test('should not return deleted channels', () => {110 const channel = {id: 'channel', team_id: 'team1', delete_at: 0};111 const deletedChannel = {id: 'deletedChannel', team_id: 'team1', delete_at: 1000};112 const getUnsortedUnfilteredChannels = Selectors.makeGetUnsortedUnfilteredChannels();113 const state = {114 entities: {115 channels: {116 channels: {117 channel,118 deletedChannel,119 },120 myMembers: {121 [channel.id]: {},122 [deletedChannel.id]: {},123 },124 },125 },126 };127 expect(getUnsortedUnfilteredChannels(state, 'team1')).toContain(channel);128 expect(getUnsortedUnfilteredChannels(state, 'team1')).not.toContain(deletedChannel);129 });130 test('should return the current channel even if it has been deleted', () => {131 const channel = {id: 'channel', team_id: 'team1', delete_at: 0};132 const deletedChannel = {id: 'deletedChannel', team_id: 'team1', delete_at: 1000};133 const getUnsortedUnfilteredChannels = Selectors.makeGetUnsortedUnfilteredChannels();134 let state = {135 entities: {136 channels: {137 channels: {138 channel,139 deletedChannel,140 },141 currentChannelId: channel.id,142 myMembers: {143 [channel.id]: {},144 [deletedChannel.id]: {},145 },146 },147 },148 };149 expect(getUnsortedUnfilteredChannels(state, 'team1')).toContain(channel);150 expect(getUnsortedUnfilteredChannels(state, 'team1')).not.toContain(deletedChannel);151 state = mergeObjects(state, {152 entities: {153 channels: {154 currentChannelId: deletedChannel.id,155 },156 },157 });158 expect(getUnsortedUnfilteredChannels(state, 'team1')).toContain(channel);159 expect(getUnsortedUnfilteredChannels(state, 'team1')).toContain(deletedChannel);160 });161 test('should memoize properly', () => {162 const getUnsortedUnfilteredChannels = Selectors.makeGetUnsortedUnfilteredChannels();163 const result = getUnsortedUnfilteredChannels(baseState, 'team1');164 // Repeat calls should return the same array165 expect(getUnsortedUnfilteredChannels(baseState, 'team1')).toBe(result);166 // Calls to a difference instance of the selector won't return the same array167 expect(result).not.toBe(Selectors.makeGetUnsortedUnfilteredChannels()(baseState, 'team1'));168 // Calls with different arguments won't return the same array169 expect(getUnsortedUnfilteredChannels(baseState, 'team2')).not.toBe(result);170 // Calls after different argumetns won't return the same array171 expect(getUnsortedUnfilteredChannels(baseState, 'team1')).not.toBe(result);172 });173});174describe('makeFilterChannelsByFavorites', () => {175 const channel1 = {id: 'channel1'};176 const channel2 = {id: 'channel2'};177 const state = {178 entities: {179 channels: {180 channels: {181 channel1,182 channel2,183 },184 },185 preferences: {186 myPreferences: {187 [getPreferenceKey(Preferences.CATEGORY_FAVORITE_CHANNEL, channel1.id)]: {value: 'true'},188 [getPreferenceKey(Preferences.CATEGORY_FAVORITE_CHANNEL, channel2.id)]: {value: 'false'},189 },190 },191 },192 };193 const channels = [channel1, channel2];194 test('should return only favorited channels for the favorites category', () => {195 const filterChanneldByFavorites = Selectors.makeFilterChannelsByFavorites();196 expect(filterChanneldByFavorites(state, channels, CategoryTypes.FAVORITES)).toMatchObject([channel1]);197 });198 test('should not return favorited channels for other categories', () => {199 const filterChanneldByFavorites = Selectors.makeFilterChannelsByFavorites();200 expect(filterChanneldByFavorites(state, channels, CategoryTypes.CUSTOM)).toMatchObject([channel2]);201 });202 test('should memoize properly', () => {203 const filterChanneldByFavorites = Selectors.makeFilterChannelsByFavorites();204 const result = filterChanneldByFavorites(state, channels, CategoryTypes.CUSTOM);205 // Repeat calls should return the same array206 expect(filterChanneldByFavorites(state, channels, CategoryTypes.CUSTOM)).toBe(result);207 // Calls to a difference instance of the selector won't return the same array208 expect(result).not.toBe(Selectors.makeFilterChannelsByFavorites()(state, channels, CategoryTypes.CUSTOM));209 // Calls with different arguments won't return the same array210 expect(filterChanneldByFavorites(state, [channel1], CategoryTypes.CUSTOM)).not.toBe(result);211 // Calls after different argumetns won't return the same array212 expect(filterChanneldByFavorites(state, channels, CategoryTypes.CUSTOM)).not.toBe(result);213 });214});215describe('makeFilterChannelsByType', () => {216 const channel1 = {id: 'channel1', type: General.OPEN_CHANNEL};217 const channel2 = {id: 'channel2', type: General.PRIVATE_CHANNEL};218 const dmChannel1 = {id: 'dmChannel1', type: General.DM_CHANNEL};219 const gmChannel1 = {id: 'gmChannel1', type: General.GM_CHANNEL};220 const state = {};221 const channels = [channel1, channel2, dmChannel1, gmChannel1];222 test('should filter out non-public channels for public category', () => {223 const filterChannelsByType = Selectors.makeFilterChannelsByType();224 expect(filterChannelsByType(state, channels, CategoryTypes.PUBLIC)).toMatchObject([channel1]);225 });226 test('should filter out non-private channels for private category', () => {227 const filterChannelsByType = Selectors.makeFilterChannelsByType();228 expect(filterChannelsByType(state, channels, CategoryTypes.PRIVATE)).toMatchObject([channel2]);229 });230 test('should filter out non-DM/GM channels for direct messages category', () => {231 const filterChannelsByType = Selectors.makeFilterChannelsByType();232 expect(filterChannelsByType(state, channels, CategoryTypes.DIRECT_MESSAGES)).toMatchObject([dmChannel1, gmChannel1]);233 });234 test('should not filter out channels for favorites category', () => {235 const filterChannelsByType = Selectors.makeFilterChannelsByType();236 expect(filterChannelsByType(state, channels, CategoryTypes.FAVORITES)).toBe(channels);237 });238});239describe('makeFilterAutoclosedDMs', () => {240 const currentUser = {id: 'currentUser'};241 const baseState = {242 entities: {243 channels: {244 currentChannelId: 'channel1',245 myMembers: {246 channel1: {},247 },248 },249 general: {250 config: {251 CloseUnusedDirectMessages: 'true',252 },253 },254 posts: {255 posts: {},256 postsInChannel: {257 channel1: [],258 },259 },260 preferences: {261 myPreferences: {262 [getPreferenceKey(Preferences.CATEGORY_SIDEBAR_SETTINGS, Preferences.CHANNEL_SIDEBAR_AUTOCLOSE_DMS)]: {value: Preferences.AUTOCLOSE_DMS_ENABLED},263 },264 },265 users: {266 currentUserId: currentUser.id,267 profiles: {268 currentUser,269 },270 },271 },272 };273 const now = Date.now();274 const cutoff = now - 7 * 24 * 60 * 60 * 1000;275 function isChannelVisiblePrecondition(state, channel) {276 return isGroupOrDirectChannelVisible(277 channel,278 getMyChannelMemberships(state),279 getConfig(state),280 getMyPreferences(state),281 getCurrentUserId(state),282 state.entities.users.profiles,283 getLastPostPerChannel(state),284 getCurrentChannelId(state),285 now,286 );287 }288 test('should hide an inactive GM channel', () => {289 const filterAutoclosedDMs = Selectors.makeFilterAutoclosedDMs(() => cutoff);290 const gmChannel = {id: 'gmChannel', type: General.GM_CHANNEL};291 const state = mergeObjects(baseState, {292 entities: {293 preferences: {294 myPreferences: {295 [getPreferenceKey(Preferences.CATEGORY_GROUP_CHANNEL_SHOW, gmChannel.id)]: {value: 'true'},296 [getPreferenceKey(Preferences.CATEGORY_CHANNEL_OPEN_TIME, gmChannel.id)]: {value: `${cutoff - 1}`},297 [getPreferenceKey(Preferences.CATEGORY_CHANNEL_APPROXIMATE_VIEW_TIME, gmChannel.id)]: {value: `${cutoff - 1}`},298 },299 },300 },301 });302 expect(isChannelVisiblePrecondition(state, gmChannel)).toBe(false);303 expect(filterAutoclosedDMs(state, [gmChannel], CategoryTypes.DIRECT_MESSAGES)).toEqual([]);304 });305 test('should show a GM channel if it was opened recently', () => {306 const filterAutoclosedDMs = Selectors.makeFilterAutoclosedDMs(() => cutoff);307 const gmChannel = {id: 'gmChannel', type: General.GM_CHANNEL};308 const state = mergeObjects(baseState, {309 entities: {310 preferences: {311 myPreferences: {312 [getPreferenceKey(Preferences.CATEGORY_GROUP_CHANNEL_SHOW, gmChannel.id)]: {value: 'true'},313 [getPreferenceKey(Preferences.CATEGORY_CHANNEL_OPEN_TIME, gmChannel.id)]: {value: `${cutoff + 1}`},314 [getPreferenceKey(Preferences.CATEGORY_CHANNEL_APPROXIMATE_VIEW_TIME, gmChannel.id)]: {value: `${cutoff - 1}`},315 },316 },317 },318 });319 expect(isChannelVisiblePrecondition(state, gmChannel)).toBe(true);320 expect(filterAutoclosedDMs(state, [gmChannel], CategoryTypes.DIRECT_MESSAGES)).toEqual([gmChannel]);321 });322 test('should show a GM channel if it was viewed recently', () => {323 const filterAutoclosedDMs = Selectors.makeFilterAutoclosedDMs(() => cutoff);324 const gmChannel = {id: 'gmChannel', type: General.GM_CHANNEL};325 const state = mergeObjects(baseState, {326 entities: {327 preferences: {328 myPreferences: {329 [getPreferenceKey(Preferences.CATEGORY_GROUP_CHANNEL_SHOW, gmChannel.id)]: {value: 'true'},330 [getPreferenceKey(Preferences.CATEGORY_CHANNEL_OPEN_TIME, gmChannel.id)]: {value: `${cutoff - 1}`},331 [getPreferenceKey(Preferences.CATEGORY_CHANNEL_APPROXIMATE_VIEW_TIME, gmChannel.id)]: {value: `${cutoff + 1}`},332 },333 },334 },335 });336 expect(isChannelVisiblePrecondition(state, gmChannel)).toBe(true);337 expect(filterAutoclosedDMs(state, [gmChannel], CategoryTypes.DIRECT_MESSAGES)).toEqual([gmChannel]);338 });339 test('should show a GM channel if it had an unloaded post made recently', () => {340 const filterAutoclosedDMs = Selectors.makeFilterAutoclosedDMs(() => cutoff);341 const gmChannel = {id: 'gmChannel', type: General.GM_CHANNEL, last_post_at: cutoff + 1};342 const state = mergeObjects(baseState, {343 entities: {344 preferences: {345 myPreferences: {346 [getPreferenceKey(Preferences.CATEGORY_GROUP_CHANNEL_SHOW, gmChannel.id)]: {value: 'true'},347 [getPreferenceKey(Preferences.CATEGORY_CHANNEL_OPEN_TIME, gmChannel.id)]: {value: `${cutoff - 1}`},348 [getPreferenceKey(Preferences.CATEGORY_CHANNEL_APPROXIMATE_VIEW_TIME, gmChannel.id)]: {value: `${cutoff - 1}`},349 },350 },351 },352 });353 expect(isChannelVisiblePrecondition(state, gmChannel)).toBe(true);354 expect(filterAutoclosedDMs(state, [gmChannel], CategoryTypes.DIRECT_MESSAGES)).toEqual([gmChannel]);355 });356 test('should show a GM channel if it had a loaded post made recently', () => {357 const filterAutoclosedDMs = Selectors.makeFilterAutoclosedDMs(() => cutoff);358 const gmChannel = {id: 'gmChannel', type: General.GM_CHANNEL};359 const state = mergeObjects(baseState, {360 entities: {361 posts: {362 posts: {363 post1: {id: 'post1', channel_id: gmChannel, create_at: cutoff + 1},364 },365 postsInChannel: {366 gmChannel: [{order: ['post1'], recent: true}],367 },368 },369 preferences: {370 myPreferences: {371 [getPreferenceKey(Preferences.CATEGORY_GROUP_CHANNEL_SHOW, gmChannel.id)]: {value: 'true'},372 [getPreferenceKey(Preferences.CATEGORY_CHANNEL_OPEN_TIME, gmChannel.id)]: {value: `${cutoff - 1}`},373 [getPreferenceKey(Preferences.CATEGORY_CHANNEL_APPROXIMATE_VIEW_TIME, gmChannel.id)]: {value: `${cutoff - 1}`},374 },375 },376 },377 });378 expect(isChannelVisiblePrecondition(state, gmChannel)).toBe(true);379 expect(filterAutoclosedDMs(state, [gmChannel], CategoryTypes.DIRECT_MESSAGES)).toEqual([gmChannel]);380 });381 test('should show an inactive GM channel if autoclosing DMs is disabled for the user', () => {382 const filterAutoclosedDMs = Selectors.makeFilterAutoclosedDMs(() => cutoff);383 const gmChannel = {id: 'gmChannel', type: General.GM_CHANNEL};384 const state = mergeObjects(baseState, {385 entities: {386 preferences: {387 myPreferences: {388 [getPreferenceKey(Preferences.CATEGORY_SIDEBAR_SETTINGS, Preferences.CHANNEL_SIDEBAR_AUTOCLOSE_DMS)]: {value: ''},389 [getPreferenceKey(Preferences.CATEGORY_GROUP_CHANNEL_SHOW, gmChannel.id)]: {value: 'true'},390 [getPreferenceKey(Preferences.CATEGORY_CHANNEL_OPEN_TIME, gmChannel.id)]: {value: `${cutoff - 1}`},391 [getPreferenceKey(Preferences.CATEGORY_CHANNEL_APPROXIMATE_VIEW_TIME, gmChannel.id)]: {value: `${cutoff - 1}`},392 },393 },394 },395 });396 expect(isChannelVisiblePrecondition(state, gmChannel)).toBe(true);397 expect(filterAutoclosedDMs(state, [gmChannel], CategoryTypes.DIRECT_MESSAGES)).toEqual([gmChannel]);398 });399 test('should show an inactive GM channel if autoclosing DMs is disabled for the server', () => {400 const filterAutoclosedDMs = Selectors.makeFilterAutoclosedDMs(() => cutoff);401 const gmChannel = {id: 'gmChannel', type: General.GM_CHANNEL};402 const state = mergeObjects(baseState, {403 entities: {404 general: {405 config: {406 CloseUnusedDirectMessages: 'false',407 },408 },409 preferences: {410 myPreferences: {411 [getPreferenceKey(Preferences.CATEGORY_SIDEBAR_SETTINGS, Preferences.CHANNEL_SIDEBAR_AUTOCLOSE_DMS)]: {value: Preferences.AUTOCLOSE_DMS_ENABLED},412 [getPreferenceKey(Preferences.CATEGORY_GROUP_CHANNEL_SHOW, gmChannel.id)]: {value: 'true'},413 [getPreferenceKey(Preferences.CATEGORY_CHANNEL_OPEN_TIME, gmChannel.id)]: {value: `${cutoff - 1}`},414 [getPreferenceKey(Preferences.CATEGORY_CHANNEL_APPROXIMATE_VIEW_TIME, gmChannel.id)]: {value: `${cutoff - 1}`},415 },416 },417 },418 });419 expect(isChannelVisiblePrecondition(state, gmChannel)).toBe(true);420 expect(filterAutoclosedDMs(state, [gmChannel], CategoryTypes.DIRECT_MESSAGES)).toEqual([gmChannel]);421 });422 test('should show a GM channel if it has unread messages', () => {423 const filterAutoclosedDMs = Selectors.makeFilterAutoclosedDMs(() => cutoff);424 const gmChannel = {id: 'gmChannel', type: General.GM_CHANNEL, total_msg_count: 1};425 const state = mergeObjects(baseState, {426 entities: {427 channels: {428 myMembers: {429 gmChannel: {msg_count: 0},430 },431 },432 preferences: {433 myPreferences: {434 [getPreferenceKey(Preferences.CATEGORY_GROUP_CHANNEL_SHOW, gmChannel.id)]: {value: 'true'},435 [getPreferenceKey(Preferences.CATEGORY_CHANNEL_OPEN_TIME, gmChannel.id)]: {value: `${cutoff - 1}`},436 [getPreferenceKey(Preferences.CATEGORY_CHANNEL_APPROXIMATE_VIEW_TIME, gmChannel.id)]: {value: `${cutoff - 1}`},437 },438 },439 },440 });441 expect(isChannelVisiblePrecondition(state, gmChannel)).toBe(true);442 expect(filterAutoclosedDMs(state, [gmChannel], CategoryTypes.DIRECT_MESSAGES)).toEqual([gmChannel]);443 });444 test('should hide an inactive DM channel', () => {445 const filterAutoclosedDMs = Selectors.makeFilterAutoclosedDMs(() => cutoff);446 const otherUser = {id: 'otherUser', delete_at: 0};447 const dmChannel = {id: 'dmChannel', name: `${currentUser.id}__${otherUser.id}`, type: General.DM_CHANNEL};448 const state = mergeObjects(baseState, {449 entities: {450 preferences: {451 myPreferences: {452 [getPreferenceKey(Preferences.CATEGORY_DIRECT_CHANNEL_SHOW, otherUser.id)]: {value: 'true'},453 [getPreferenceKey(Preferences.CATEGORY_CHANNEL_OPEN_TIME, dmChannel.id)]: {value: `${cutoff - 1}`},454 [getPreferenceKey(Preferences.CATEGORY_CHANNEL_APPROXIMATE_VIEW_TIME, dmChannel.id)]: {value: `${cutoff - 1}`},455 },456 },457 users: {458 profiles: {459 otherUser,460 },461 },462 },463 });464 expect(isChannelVisiblePrecondition(state, dmChannel)).toBe(false);465 expect(filterAutoclosedDMs(state, [dmChannel], CategoryTypes.DIRECT_MESSAGES)).toEqual([]);466 });467 test('should show a DM channel if it was opened recently', () => {468 const filterAutoclosedDMs = Selectors.makeFilterAutoclosedDMs(() => cutoff);469 const otherUser = {id: 'otherUser', delete_at: 0};470 const dmChannel = {id: 'dmChannel', name: `${currentUser.id}__${otherUser.id}`, type: General.DM_CHANNEL};471 const state = mergeObjects(baseState, {472 entities: {473 preferences: {474 myPreferences: {475 [getPreferenceKey(Preferences.CATEGORY_DIRECT_CHANNEL_SHOW, otherUser.id)]: {value: 'true'},476 [getPreferenceKey(Preferences.CATEGORY_CHANNEL_OPEN_TIME, dmChannel.id)]: {value: `${cutoff + 1}`},477 [getPreferenceKey(Preferences.CATEGORY_CHANNEL_APPROXIMATE_VIEW_TIME, dmChannel.id)]: {value: `${cutoff - 1}`},478 },479 },480 users: {481 profiles: {482 otherUser,483 },484 },485 },486 });487 expect(isChannelVisiblePrecondition(state, dmChannel)).toBe(true);488 expect(filterAutoclosedDMs(state, [dmChannel], CategoryTypes.DIRECT_MESSAGES)).toEqual([dmChannel]);489 });490 test('should show a DM channel with a deactivated user if its the current channel', () => {491 const filterAutoclosedDMs = Selectors.makeFilterAutoclosedDMs(() => cutoff);492 const otherUser = {id: 'otherUser', delete_at: cutoff + 2};493 const dmChannel = {id: 'dmChannel', name: `${currentUser.id}__${otherUser.id}`, type: General.DM_CHANNEL};494 const state = mergeObjects(baseState, {495 entities: {496 channels: {497 currentChannelId: 'dmChannel',498 },499 preferences: {500 myPreferences: {501 [getPreferenceKey(Preferences.CATEGORY_DIRECT_CHANNEL_SHOW, otherUser.id)]: {value: 'true'},502 [getPreferenceKey(Preferences.CATEGORY_CHANNEL_OPEN_TIME, dmChannel.id)]: {value: `${cutoff + 1}`},503 [getPreferenceKey(Preferences.CATEGORY_CHANNEL_APPROXIMATE_VIEW_TIME, dmChannel.id)]: {value: `${cutoff - 1}`},504 },505 },506 users: {507 profiles: {508 otherUser,509 },510 },511 },512 });513 expect(isChannelVisiblePrecondition(state, dmChannel)).toBe(true);514 expect(filterAutoclosedDMs(state, [dmChannel], CategoryTypes.DIRECT_MESSAGES)).toEqual([dmChannel]);515 });516 test('should hide a DM channel with a deactivated user if it is not the current channel', () => {517 const filterAutoclosedDMs = Selectors.makeFilterAutoclosedDMs(() => cutoff);518 const otherUser = {id: 'otherUser', delete_at: cutoff + 2};519 const dmChannel = {id: 'dmChannel', name: `${currentUser.id}__${otherUser.id}`, type: General.DM_CHANNEL};520 const state = mergeObjects(baseState, {521 entities: {522 channels: {523 currentChannelId: 'channel2',524 },525 preferences: {526 myPreferences: {527 [getPreferenceKey(Preferences.CATEGORY_DIRECT_CHANNEL_SHOW, otherUser.id)]: {value: 'true'},528 [getPreferenceKey(Preferences.CATEGORY_CHANNEL_OPEN_TIME, dmChannel.id)]: {value: `${cutoff + 1}`},529 [getPreferenceKey(Preferences.CATEGORY_CHANNEL_APPROXIMATE_VIEW_TIME, dmChannel.id)]: {value: `${cutoff - 1}`},530 },531 },532 users: {533 profiles: {534 otherUser,535 },536 },537 },538 });539 expect(isChannelVisiblePrecondition(state, dmChannel)).toBe(false);540 expect(filterAutoclosedDMs(state, [dmChannel], CategoryTypes.DIRECT_MESSAGES)).toEqual([]);541 });542 test('should show a DM channel with a deactivated user if it is not the current channel but it has been opened since the user was deactivated', () => {543 const filterAutoclosedDMs = Selectors.makeFilterAutoclosedDMs(() => cutoff);544 const otherUser = {id: 'otherUser', delete_at: cutoff + 2};545 const dmChannel = {id: 'dmChannel', name: `${currentUser.id}__${otherUser.id}`, type: General.DM_CHANNEL};546 const state = mergeObjects(baseState, {547 entities: {548 channels: {549 currentChannelId: 'dmChannel',550 },551 preferences: {552 myPreferences: {553 [getPreferenceKey(Preferences.CATEGORY_DIRECT_CHANNEL_SHOW, otherUser.id)]: {value: 'true'},554 [getPreferenceKey(Preferences.CATEGORY_CHANNEL_OPEN_TIME, dmChannel.id)]: {value: `${cutoff + 3}`},555 [getPreferenceKey(Preferences.CATEGORY_CHANNEL_APPROXIMATE_VIEW_TIME, dmChannel.id)]: {value: `${cutoff - 1}`},556 },557 },558 users: {559 profiles: {560 otherUser,561 },562 },563 },564 });565 expect(isChannelVisiblePrecondition(state, dmChannel)).toBe(true);566 expect(filterAutoclosedDMs(state, [dmChannel], CategoryTypes.DIRECT_MESSAGES)).toEqual([dmChannel]);567 });568 test('should return the original array when no items are removed', () => {569 const filterAutoclosedDMs = Selectors.makeFilterAutoclosedDMs(() => cutoff);570 const channel1 = {id: 'channel1', type: General.PUBLIC_CHANNEL};571 const state = baseState;572 const channels = [channel1];573 expect(filterAutoclosedDMs(state, channels, CategoryTypes.DIRECT_MESSAGES)).toBe(channels);574 });575});576describe('makeFilterManuallyClosedDMs', () => {577 const currentUser = {id: 'currentUser'};578 const otherUser1 = {id: 'otherUser1'};579 const otherUser2 = {id: 'otherUser2'};580 const otherUser3 = {id: 'otherUser3'};581 const baseState = {582 entities: {583 channels: {584 myMembers: {},585 },586 preferences: {587 myPreferences: {},588 },589 users: {590 currentUserId: currentUser.id,591 },592 },593 };594 test('should filter DMs based on preferences', () => {595 const filterManuallyClosedDMs = Selectors.makeFilterManuallyClosedDMs();596 const dmChannel1 = {id: 'dmChannel1', type: General.DM_CHANNEL, name: `${currentUser.id}__${otherUser1.id}`};597 const dmChannel2 = {id: 'dmChannel2', type: General.DM_CHANNEL, name: `${currentUser.id}__${otherUser2.id}`};598 const state = mergeObjects(baseState, {599 entities: {600 preferences: {601 myPreferences: {602 [getPreferenceKey(Preferences.CATEGORY_DIRECT_CHANNEL_SHOW, otherUser1.id)]: {value: 'false'},603 [getPreferenceKey(Preferences.CATEGORY_DIRECT_CHANNEL_SHOW, otherUser2.id)]: {value: 'true'},604 },605 },606 },607 });608 expect(filterManuallyClosedDMs(state, [dmChannel1, dmChannel2])).toMatchObject([dmChannel2]);609 });610 test('should filter GMs based on preferences', () => {611 const filterManuallyClosedDMs = Selectors.makeFilterManuallyClosedDMs();612 const gmChannel1 = {id: 'gmChannel1', type: General.GM_CHANNEL};613 const gmChannel2 = {id: 'gmChannel2', type: General.GM_CHANNEL};614 const state = mergeObjects(baseState, {615 entities: {616 preferences: {617 myPreferences: {618 [getPreferenceKey(Preferences.CATEGORY_GROUP_CHANNEL_SHOW, gmChannel1.id)]: {value: 'true'},619 [getPreferenceKey(Preferences.CATEGORY_GROUP_CHANNEL_SHOW, gmChannel2.id)]: {value: 'false'},620 },621 },622 },623 });624 expect(filterManuallyClosedDMs(state, [gmChannel1, gmChannel2])).toMatchObject([gmChannel1]);625 });626 test('should show unread DMs and GMs, regardless of preferences', () => {627 const filterManuallyClosedDMs = Selectors.makeFilterManuallyClosedDMs();628 const dmChannel1 = {id: 'dmChannel1', type: General.DM_CHANNEL, name: `${currentUser.id}__${otherUser1.id}`, total_msg_count: 1};629 const dmChannel2 = {id: 'dmChannel2', type: General.DM_CHANNEL, name: `${currentUser.id}__${otherUser2.id}`, total_msg_count: 0};630 const gmChannel1 = {id: 'gmChannel1', type: General.GM_CHANNEL, total_msg_count: 1};631 const gmChannel2 = {id: 'gmChannel2', type: General.GM_CHANNEL, total_msg_count: 0};632 const state = mergeObjects(baseState, {633 entities: {634 channels: {635 myMembers: {636 dmChannel1: {msg_count: 0},637 dmChannel2: {msg_count: 0},638 gmChannel1: {msg_count: 0},639 gmChannel2: {msg_count: 0},640 },641 },642 preferences: {643 myPreferences: {644 [getPreferenceKey(Preferences.CATEGORY_DIRECT_CHANNEL_SHOW, otherUser1.id)]: {value: 'false'},645 [getPreferenceKey(Preferences.CATEGORY_DIRECT_CHANNEL_SHOW, otherUser2.id)]: {value: 'false'},646 [getPreferenceKey(Preferences.CATEGORY_GROUP_CHANNEL_SHOW, gmChannel1.id)]: {value: 'false'},647 [getPreferenceKey(Preferences.CATEGORY_GROUP_CHANNEL_SHOW, gmChannel2.id)]: {value: 'false'},648 },649 },650 },651 });652 expect(filterManuallyClosedDMs(state, [dmChannel1, dmChannel2, gmChannel1, gmChannel2])).toEqual([dmChannel1, gmChannel1]);653 });654 test('should show the current channel, regardless of preferences', () => {655 const filterManuallyClosedDMs = Selectors.makeFilterManuallyClosedDMs();656 const dmChannel1 = {id: 'dmChannel1', type: General.DM_CHANNEL, name: `${currentUser.id}__${otherUser1.id}`};657 const gmChannel1 = {id: 'gmChannel1', type: General.GM_CHANNEL};658 let state = mergeObjects(baseState, {659 entities: {660 preferences: {661 myPreferences: {662 [getPreferenceKey(Preferences.CATEGORY_DIRECT_CHANNEL_SHOW, otherUser1.id)]: {value: 'false'},663 [getPreferenceKey(Preferences.CATEGORY_GROUP_CHANNEL_SHOW, gmChannel1.id)]: {value: 'false'},664 },665 },666 },667 });668 expect(filterManuallyClosedDMs(state, [dmChannel1, gmChannel1])).toEqual([]);669 state = mergeObjects(baseState, {670 entities: {671 channels: {672 currentChannelId: dmChannel1.id,673 },674 },675 });676 expect(filterManuallyClosedDMs(state, [dmChannel1, gmChannel1])).toEqual([dmChannel1]);677 state = mergeObjects(baseState, {678 entities: {679 channels: {680 currentChannelId: gmChannel1.id,681 },682 },683 });684 expect(filterManuallyClosedDMs(state, [dmChannel1, gmChannel1])).toEqual([gmChannel1]);685 });686 test('should not filter other channels', () => {687 const filterManuallyClosedDMs = Selectors.makeFilterManuallyClosedDMs();688 const channel1 = {id: 'channel1', type: General.OPEN_CHANNEL};689 const channel2 = {id: 'channel2', type: General.PRIVATE_CHANNEL};690 const state = baseState;691 const channels = [channel1, channel2];692 expect(filterManuallyClosedDMs(state, channels)).toBe(channels);693 });694});695describe('makeSortChannelsByName', () => {696 const currentUser = {id: 'currentUser', locale: 'en'};697 const baseState = {698 entities: {699 channels: {700 myMembers: {},701 },702 users: {703 currentUserId: currentUser.id,704 profiles: {705 currentUser,706 },707 },708 },709 };710 test('should sort channels by display name', () => {711 const sortChannelsByName = Selectors.makeSortChannelsByName();712 const channel1 = {id: 'channel1', display_name: 'Carrot'};713 const channel2 = {id: 'channel2', display_name: 'Apple'};714 const channel3 = {id: 'channel3', display_name: 'Banana'};715 const channels = [channel1, channel2, channel3];716 expect(sortChannelsByName(baseState, channels)).toEqual([channel2, channel3, channel1]);717 });718 test('should sort channels by display name with numbers', () => {719 const sortChannelsByName = Selectors.makeSortChannelsByName();720 const channel1 = {id: 'channel1', display_name: 'Channel 10'};721 const channel2 = {id: 'channel2', display_name: 'Channel 1'};722 const channel3 = {id: 'channel3', display_name: 'Channel 11'};723 const channel4 = {id: 'channel4', display_name: 'Channel 1a'};724 const channels = [channel1, channel2, channel3, channel4];725 expect(sortChannelsByName(baseState, channels)).toEqual([channel2, channel4, channel1, channel3]);726 });727 test('should sort muted channels last', () => {728 const sortChannelsByName = Selectors.makeSortChannelsByName();729 const state = mergeObjects(baseState, {730 entities: {731 channels: {732 myMembers: {733 channel1: {notify_props: {mark_unread: General.MENTION}},734 channel3: {notify_props: {mark_unread: General.MENTION}},735 channel4: {notify_props: {mark_unread: 'all'}},736 },737 },738 },739 });740 const channel1 = {id: 'channel1', display_name: 'Carrot'};741 const channel2 = {id: 'channel2', display_name: 'Apple'};742 const channel3 = {id: 'channel3', display_name: 'Banana'};743 const channel4 = {id: 'channel4', display_name: 'Dragonfruit'};744 const channels = [channel1, channel2, channel3, channel4];745 expect(sortChannelsByName(state, channels)).toEqual([channel2, channel4, channel3, channel1]);746 });747});748describe('makeSortChannelsByNameWithDMs', () => {749 const currentUser = {id: 'currentUser', username: 'currentUser', first_name: 'Current', last_name: 'User', locale: 'en'};750 const otherUser1 = {id: 'otherUser1', username: 'otherUser1', first_name: 'Other', last_name: 'User', locale: 'en'};751 const otherUser2 = {id: 'otherUser2', username: 'otherUser2', first_name: 'Another', last_name: 'User', locale: 'en'};752 const channel1 = {id: 'channel1', type: General.OPEN_CHANNEL, display_name: 'Zebra'};753 const channel2 = {id: 'channel2', type: General.PRIVATE_CHANNEL, display_name: 'Aardvark'};754 const channel3 = {id: 'channel3', type: General.OPEN_CHANNEL, display_name: 'Bear'};755 const dmChannel1 = {id: 'dmChannel1', type: General.DM_CHANNEL, display_name: '', name: `${currentUser.id}__${otherUser1.id}`};756 const dmChannel2 = {id: 'dmChannel2', type: General.DM_CHANNEL, display_name: '', name: `${otherUser2.id}__${currentUser.id}`};757 const gmChannel1 = {id: 'gmChannel1', type: General.GM_CHANNEL, display_name: `${currentUser.username}, ${otherUser1.username}, ${otherUser2.username}`, name: 'gmChannel1'};758 const baseState = {759 entities: {760 channels: {761 myMembers: {},762 },763 general: {764 config: {},765 },766 preferences: {767 myPreferences: {768 [getPreferenceKey(Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.NAME_NAME_FORMAT)]: {value: Preferences.DISPLAY_PREFER_FULL_NAME},769 },770 },771 users: {772 currentUserId: currentUser.id,773 profiles: {774 currentUser,775 otherUser1,776 otherUser2,777 },778 },779 },780 };781 test('should sort regular channels by display name', () => {782 const sortChannelsByNameWithDMs = Selectors.makeSortChannelsByNameWithDMs();783 expect(sortChannelsByNameWithDMs(baseState, [784 channel1,785 channel2,786 channel3,787 ])).toMatchObject([788 channel2, // Aardvark789 channel3, // Bear790 channel1, // Zebra791 ]);792 });793 test('should sort DM channels by the display name of the other user', () => {794 const sortChannelsByNameWithDMs = Selectors.makeSortChannelsByNameWithDMs();795 expect(sortChannelsByNameWithDMs(baseState, [796 channel1,797 channel2,798 channel3,799 dmChannel1,800 dmChannel2,801 ])).toMatchObject([802 channel2, // Aardvark803 dmChannel2, // Another User804 channel3, // Bear805 dmChannel1, // Other User806 channel1, // Zebra807 ]);808 });809 test('should sort GM channels by the display name of the other users', () => {810 const sortChannelsByNameWithDMs = Selectors.makeSortChannelsByNameWithDMs();811 let state = baseState;812 expect(sortChannelsByNameWithDMs(state, [813 channel1,814 channel2,815 channel3,816 gmChannel1,817 ])).toMatchObject([818 channel2, // Aardvark819 gmChannel1, // Another User, Other User820 channel3, // Bear821 channel1, // Zebra822 ]);823 state = mergeObjects(state, {824 entities: {825 users: {826 currentUserId: otherUser2.id,827 },828 },829 });830 expect(sortChannelsByNameWithDMs(state, [831 channel1,832 channel2,833 channel3,834 gmChannel1,835 ])).toMatchObject([836 channel2, // Aardvark837 channel3, // Bear838 gmChannel1, // Current User, Other User839 channel1, // Zebra840 ]);841 });842 test('should sort muted channels last', () => {843 const sortChannelsByNameWithDMs = Selectors.makeSortChannelsByNameWithDMs();844 const state = mergeObjects(baseState, {845 entities: {846 channels: {847 myMembers: {848 channel3: {notify_props: {mark_unread: General.MENTION}},849 dmChannel1: {notify_props: {mark_unread: General.MENTION}},850 dmChannel2: {notify_props: {mark_unread: 'all'}},851 gmChannel1: {notify_props: {mark_unread: General.MENTION}},852 },853 },854 },855 });856 expect(sortChannelsByNameWithDMs(state, [857 channel1,858 channel2,859 channel3,860 dmChannel1,861 dmChannel2,862 gmChannel1,863 ])).toMatchObject([864 channel2, // Aardvark865 dmChannel2, // Another User866 channel1, // Zebra867 gmChannel1, // Another User, Other User (Muted)868 channel3, // Bear (Muted)869 dmChannel1, // Other User (Muted)870 ]);871 });872});873describe('makeGetChannelsForCategory', () => {874 const currentUser = {id: 'currentUser', username: 'currentUser', first_name: 'Current', last_name: 'User', locale: 'en'};875 const otherUser1 = {id: 'otherUser1', username: 'otherUser1', first_name: 'Other', last_name: 'User', locale: 'en'};876 const otherUser2 = {id: 'otherUser2', username: 'otherUser2', first_name: 'Another', last_name: 'User', locale: 'en'};877 const channel1 = {id: 'channel1', type: General.OPEN_CHANNEL, team_id: 'team1', display_name: 'Zebra', delete_at: 0};878 const channel2 = {id: 'channel2', type: General.PRIVATE_CHANNEL, team_id: 'team1', display_name: 'Aardvark', delete_at: 0};879 const channel3 = {id: 'channel3', type: General.OPEN_CHANNEL, team_id: 'team1', display_name: 'Bear', delete_at: 0};880 const dmChannel1 = {id: 'dmChannel1', type: General.DM_CHANNEL, team_id: '', display_name: '', name: `${currentUser.id}__${otherUser1.id}`, delete_at: 0};881 const dmChannel2 = {id: 'dmChannel2', type: General.DM_CHANNEL, team_id: '', display_name: '', name: `${otherUser2.id}__${currentUser.id}`, delete_at: 0};882 const gmChannel1 = {id: 'gmChannel1', type: General.GM_CHANNEL, team_id: '', display_name: `${currentUser.username}, ${otherUser1.username}, ${otherUser2.username}`, name: 'gmChannel1', delete_at: 0};883 const favoritesCategory = {id: 'favoritesCategory', team_id: 'team1', display_name: CategoryTypes.FAVORITES, type: CategoryTypes.FAVORITES};884 const publicCategory = {id: 'publicCategory', team_id: 'team1', display_name: 'Public Channels', type: CategoryTypes.PUBLIC};885 const privateCategory = {id: 'privateCategory', team_id: 'team1', display_name: 'Private Channels', type: CategoryTypes.PRIVATE};886 const directMessagesCategory = {id: 'directMessagesCategory', team_id: 'team1', display_name: 'Direct Messages', type: CategoryTypes.DIRECT_MESSAGES};887 const state = {888 entities: {889 channelCategories: {890 byId: {891 favoritesCategory,892 publicCategory,893 privateCategory,894 directMessagesCategory,895 },896 },897 channels: {898 channels: {899 channel1,900 channel2,901 channel3,902 dmChannel1,903 dmChannel2,904 gmChannel1,905 },906 myMembers: {907 [channel1.id]: {},908 [channel2.id]: {},909 [channel3.id]: {},910 [dmChannel1.id]: {},911 [dmChannel2.id]: {},912 [gmChannel1.id]: {},913 },914 },915 general: {916 config: {},917 },918 posts: {919 posts: {},920 postsInChannel: {},921 },922 preferences: {923 myPreferences: {924 [getPreferenceKey(Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.NAME_NAME_FORMAT)]: {value: Preferences.DISPLAY_PREFER_FULL_NAME},925 [getPreferenceKey(Preferences.CATEGORY_DIRECT_CHANNEL_SHOW, otherUser1.id)]: {value: 'true'},926 [getPreferenceKey(Preferences.CATEGORY_DIRECT_CHANNEL_SHOW, otherUser2.id)]: {value: 'true'},927 [getPreferenceKey(Preferences.CATEGORY_FAVORITE_CHANNEL, channel1.id)]: {value: 'true'},928 [getPreferenceKey(Preferences.CATEGORY_FAVORITE_CHANNEL, dmChannel2.id)]: {value: 'true'},929 [getPreferenceKey(Preferences.CATEGORY_GROUP_CHANNEL_SHOW, gmChannel1.id)]: {value: 'true'},930 },931 },932 users: {933 currentUserId: currentUser.id,934 profiles: {935 currentUser,936 otherUser1,937 otherUser2,938 },939 },940 },941 };942 test('should return sorted and filtered channels for favorites category', () => {943 const getChannelsForCategory = Selectors.makeGetChannelsForCategory();944 expect(getChannelsForCategory(state, favoritesCategory)).toMatchObject([dmChannel2, channel1]);945 });946 test('should return sorted and filtered channels for public category', () => {947 const getChannelsForCategory = Selectors.makeGetChannelsForCategory();948 expect(getChannelsForCategory(state, publicCategory)).toMatchObject([channel3]);949 });950 test('should return sorted and filtered channels for private category', () => {951 const getChannelsForCategory = Selectors.makeGetChannelsForCategory();952 expect(getChannelsForCategory(state, privateCategory)).toMatchObject([channel2]);953 });954 test('should return sorted and filtered channels for direct messages category', () => {955 const getChannelsForCategory = Selectors.makeGetChannelsForCategory();956 expect(getChannelsForCategory(state, directMessagesCategory)).toMatchObject([gmChannel1, dmChannel1]);957 });958});959describe('makeGetChannelsByCategory', () => {960 const currentUser = {id: 'currentUser', username: 'currentUser', first_name: 'Current', last_name: 'User', locale: 'en'};961 const otherUser1 = {id: 'otherUser1', username: 'otherUser1', first_name: 'Other', last_name: 'User', locale: 'en'};962 const otherUser2 = {id: 'otherUser2', username: 'otherUser2', first_name: 'Another', last_name: 'User', locale: 'en'};963 const channel1 = {id: 'channel1', type: General.OPEN_CHANNEL, team_id: 'team1', display_name: 'Zebra', delete_at: 0};964 const channel2 = {id: 'channel2', type: General.PRIVATE_CHANNEL, team_id: 'team1', display_name: 'Aardvark', delete_at: 0};965 const channel3 = {id: 'channel3', type: General.OPEN_CHANNEL, team_id: 'team1', display_name: 'Bear', delete_at: 0};966 const dmChannel1 = {id: 'dmChannel1', type: General.DM_CHANNEL, team_id: '', display_name: '', name: `${currentUser.id}__${otherUser1.id}`, delete_at: 0};967 const dmChannel2 = {id: 'dmChannel2', type: General.DM_CHANNEL, team_id: '', display_name: '', name: `${otherUser2.id}__${currentUser.id}`, delete_at: 0};968 const gmChannel1 = {id: 'gmChannel1', type: General.GM_CHANNEL, team_id: '', display_name: `${currentUser.username}, ${otherUser1.username}, ${otherUser2.username}`, name: 'gmChannel1', delete_at: 0};969 const favoritesCategory = {id: 'favoritesCategory', team_id: 'team1', display_name: CategoryTypes.FAVORITES, type: CategoryTypes.FAVORITES};970 const publicCategory = {id: 'publicCategory', team_id: 'team1', display_name: 'Public Channels', type: CategoryTypes.PUBLIC};971 const privateCategory = {id: 'privateCategory', team_id: 'team1', display_name: 'Private Channels', type: CategoryTypes.PRIVATE};972 const directMessagesCategory = {id: 'directMessagesCategory', team_id: 'team1', display_name: 'Direct Messages', type: CategoryTypes.DIRECT_MESSAGES};973 const baseState = {974 entities: {975 channelCategories: {976 byId: {977 favoritesCategory,978 publicCategory,979 privateCategory,980 directMessagesCategory,981 },982 orderByTeam: {983 team1: [984 favoritesCategory.id,985 publicCategory.id,986 privateCategory.id,987 directMessagesCategory.id,988 ],989 },990 },991 channels: {992 channels: {993 channel1,994 channel2,995 channel3,996 dmChannel1,997 dmChannel2,998 gmChannel1,999 },1000 myMembers: {1001 [channel1.id]: {},1002 [channel2.id]: {},1003 [channel3.id]: {},1004 [dmChannel1.id]: {},1005 [dmChannel2.id]: {},1006 [gmChannel1.id]: {},1007 },1008 },1009 general: {1010 config: {},1011 },1012 posts: {1013 posts: {},1014 postsInChannel: {},1015 },1016 preferences: {1017 myPreferences: {1018 [getPreferenceKey(Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.NAME_NAME_FORMAT)]: {value: Preferences.DISPLAY_PREFER_FULL_NAME},1019 [getPreferenceKey(Preferences.CATEGORY_DIRECT_CHANNEL_SHOW, otherUser1.id)]: {value: 'true'},1020 [getPreferenceKey(Preferences.CATEGORY_DIRECT_CHANNEL_SHOW, otherUser2.id)]: {value: 'true'},1021 [getPreferenceKey(Preferences.CATEGORY_FAVORITE_CHANNEL, channel1.id)]: {value: 'true'},1022 [getPreferenceKey(Preferences.CATEGORY_FAVORITE_CHANNEL, dmChannel2.id)]: {value: 'true'},1023 [getPreferenceKey(Preferences.CATEGORY_GROUP_CHANNEL_SHOW, gmChannel1.id)]: {value: 'true'},1024 },1025 },1026 users: {1027 currentUserId: currentUser.id,1028 profiles: {1029 currentUser,1030 otherUser1,1031 otherUser2,1032 },1033 },1034 },1035 };1036 test('should return channels for all categories', () => {1037 const getChannelsByCategory = Selectors.makeGetChannelsByCategory();1038 expect(getChannelsByCategory(baseState, 'team1')).toEqual({1039 favoritesCategory: [dmChannel2, channel1],1040 publicCategory: [channel3],1041 privateCategory: [channel2],1042 directMessagesCategory: [gmChannel1, dmChannel1],1043 });1044 });1045 describe('memoization', () => {1046 test('should return the same object when called with the same state', () => {1047 const getChannelsByCategory = Selectors.makeGetChannelsByCategory();1048 expect(getChannelsByCategory(baseState, 'team1')).toBe(getChannelsByCategory(baseState, 'team1'));1049 });1050 test('should return the same object when unrelated state changes', () => {1051 const getChannelsByCategory = Selectors.makeGetChannelsByCategory();1052 const state = mergeObjects(baseState, {1053 views: {1054 something: 7,1055 },1056 });1057 const previousResult = getChannelsByCategory(baseState, 'team1');1058 const result = getChannelsByCategory(state, 'team1');1059 expect(result).toBe(previousResult);1060 });1061 test('should return a new object when user profiles change', () => {1062 // This behaviour isn't ideal, but it's better than the previous version which returns a new object1063 // whenever anything user-related changes1064 const getChannelsByCategory = Selectors.makeGetChannelsByCategory();1065 const state = mergeObjects(baseState, {1066 entities: {1067 users: {1068 profiles: {1069 newUser: {id: 'newUser'},1070 },1071 },1072 },1073 });1074 const previousResult = getChannelsByCategory(baseState, 'team1');1075 const result = getChannelsByCategory(state, 'team1');1076 expect(result).not.toBe(previousResult);1077 expect(result).toEqual(previousResult);1078 // Categories not containing DMs/GMs should still remain the same1079 expect(result.favoritesCategory).not.toBe(previousResult.favoritesCategory);1080 expect(result.favoritesCategory).toEqual(previousResult.favoritesCategory);1081 expect(result.publicCategory).toBe(previousResult.publicCategory);1082 expect(result.privateCategory).toBe(previousResult.privateCategory);1083 expect(result.directMessagesCategory).not.toBe(previousResult.directMessagesCategory);1084 expect(result.directMessagesCategory).toEqual(previousResult.directMessagesCategory);1085 });1086 test('should return the same object when other user state changes', () => {1087 const getChannelsByCategory = Selectors.makeGetChannelsByCategory();1088 const state = mergeObjects(baseState, {1089 entities: {1090 users: {1091 statuses: {1092 otherUser1: 'offline',1093 },1094 },1095 },1096 });1097 const previousResult = getChannelsByCategory(baseState, 'team1');1098 const result = getChannelsByCategory(state, 'team1');1099 expect(result).toBe(previousResult);1100 });1101 test('should return a new object when preferences change', () => {1102 const getChannelsByCategory = Selectors.makeGetChannelsByCategory();1103 const state = mergeObjects(baseState, {1104 entities: {1105 preferences: {1106 myPreferences: {1107 [getPreferenceKey('abc', '123')]: {value: 'true'},1108 },1109 },1110 },1111 });1112 const previousResult = getChannelsByCategory(baseState, 'team1');1113 const result = getChannelsByCategory(state, 'team1');1114 expect(result).not.toBe(previousResult);1115 expect(result).toEqual(previousResult);1116 });1117 test('should return a new object when a DM is closed', () => {1118 const getChannelsByCategory = Selectors.makeGetChannelsByCategory();1119 const state = mergeObjects(baseState, {1120 entities: {1121 preferences: {1122 myPreferences: {1123 [getPreferenceKey(Preferences.CATEGORY_DIRECT_CHANNEL_SHOW, otherUser1.id)]: {value: 'false'},1124 },1125 },1126 },1127 });1128 const previousResult = getChannelsByCategory(baseState, 'team1');1129 const result = getChannelsByCategory(state, 'team1');1130 expect(result).not.toBe(previousResult);1131 expect(result.favoritesCategory).toEqual(previousResult.favoritesCategory);1132 expect(result.publicCategory).toEqual(previousResult.publicCategory);1133 expect(result.privateCategory).toEqual(previousResult.privateCategory);1134 expect(result.directMessagesCategory).not.toEqual(previousResult.directMessagesCategory);1135 });1136 });...

Full Screen

Full Screen

channels.test.js

Source:channels.test.js Github

copy

Full Screen

1// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.2// See LICENSE.txt for license information.3import {ChannelTypes, UserTypes} from 'action_types';4import deepFreeze from 'utils/deep_freeze';5import channelsReducer, * as Reducers from './channels';6import {Permissions} from '../../constants';7describe('channels', () => {8 describe('RECEIVED_CHANNEL_DELETED', () => {9 test('should mark channel as deleted', () => {10 const state = deepFreeze({11 channelsInTeam: {},12 currentChannelId: '',13 groupsAssociatedToChannel: {},14 myMembers: {},15 stats: {},16 totalCount: 0,17 manuallyUnread: {},18 membersInChannel: {},19 channels: {20 channel1: {21 id: 'channel1',22 },23 channel2: {24 id: 'channel2',25 },26 },27 channelModerations: {},28 channelMemberCountsByGroup: {},29 });30 const nextState = channelsReducer(state, {31 type: ChannelTypes.RECEIVED_CHANNEL_DELETED,32 data: {33 id: 'channel1',34 deleteAt: 1000,35 },36 });37 expect(nextState).not.toBe(state);38 expect(nextState.channels.channel1).toEqual({39 id: 'channel1',40 delete_at: 1000,41 });42 expect(nextState.channels.channel2).toBe(state.channels.channel2);43 });44 test('should do nothing for a channel that is not loaded', () => {45 const state = deepFreeze({46 channelsInTeam: {},47 currentChannelId: '',48 groupsAssociatedToChannel: {},49 myMembers: {},50 stats: {},51 totalCount: 0,52 manuallyUnread: {},53 membersInChannel: {},54 channels: {55 channel1: {56 id: 'channel1',57 },58 channel2: {59 id: 'channel2',60 },61 },62 channelModerations: {},63 channelMemberCountsByGroup: {},64 });65 const nextState = channelsReducer(state, {66 type: ChannelTypes.RECEIVED_CHANNEL_DELETED,67 data: {68 id: 'channel3',69 deleteAt: 1000,70 },71 });72 expect(nextState).toBe(state);73 });74 });75 describe('RECEIVED_CHANNEL_UNARCHIVED', () => {76 test('should mark channel as active', () => {77 const state = deepFreeze({78 channelsInTeam: {},79 currentChannelId: '',80 groupsAssociatedToChannel: {},81 myMembers: {},82 stats: {},83 totalCount: 0,84 manuallyUnread: {},85 membersInChannel: {},86 channels: {87 channel1: {88 id: 'channel1',89 delete_at: 1000,90 },91 channel2: {92 id: 'channel2',93 },94 },95 channelModerations: {},96 channelMemberCountsByGroup: {},97 });98 const nextState = channelsReducer(state, {99 type: ChannelTypes.RECEIVED_CHANNEL_UNARCHIVED,100 data: {101 id: 'channel1',102 },103 });104 expect(nextState).not.toBe(state);105 expect(nextState.channels.channel1).toEqual({106 id: 'channel1',107 delete_at: 0,108 });109 expect(nextState.channels.channel2).toBe(state.channels.channel2);110 });111 test('should do nothing for a channel that is not loaded', () => {112 const state = deepFreeze({113 channelsInTeam: {},114 currentChannelId: '',115 groupsAssociatedToChannel: {},116 myMembers: {},117 stats: {},118 totalCount: 0,119 manuallyUnread: {},120 membersInChannel: {},121 channels: {122 channel1: {123 id: 'channel1',124 },125 channel2: {126 id: 'channel2',127 },128 },129 channelModerations: {},130 channelMemberCountsByGroup: {},131 });132 const nextState = channelsReducer(state, {133 type: ChannelTypes.RECEIVED_CHANNEL_UNARCHIVED,134 data: {135 id: 'channel3',136 },137 });138 expect(nextState).toBe(state);139 });140 });141 describe('UPDATE_CHANNEL_HEADER', () => {142 test('should update channel header', () => {143 const state = deepFreeze({144 channelsInTeam: {},145 currentChannelId: '',146 groupsAssociatedToChannel: {},147 myMembers: {},148 stats: {},149 totalCount: 0,150 manuallyUnread: {},151 membersInChannel: {},152 channels: {153 channel1: {154 id: 'channel1',155 header: 'old',156 },157 channel2: {158 id: 'channel2',159 },160 },161 channelModerations: {},162 channelMemberCountsByGroup: {},163 });164 const nextState = channelsReducer(state, {165 type: ChannelTypes.UPDATE_CHANNEL_HEADER,166 data: {167 channelId: 'channel1',168 header: 'new',169 },170 });171 expect(nextState).not.toBe(state);172 expect(nextState.channels.channel1).toEqual({173 id: 'channel1',174 header: 'new',175 });176 expect(nextState.channels.channel2).toBe(state.channels.channel2);177 });178 test('should do nothing for a channel that is not loaded', () => {179 const state = deepFreeze({180 channelsInTeam: {},181 currentChannelId: '',182 groupsAssociatedToChannel: {},183 myMembers: {},184 stats: {},185 totalCount: 0,186 manuallyUnread: {},187 membersInChannel: {},188 channels: {189 channel1: {190 id: 'channel1',191 header: 'old',192 },193 channel2: {194 id: 'channel2',195 },196 },197 channelModerations: {},198 channelMemberCountsByGroup: {},199 });200 const nextState = channelsReducer(state, {201 type: ChannelTypes.UPDATE_CHANNEL_HEADER,202 data: {203 channelId: 'channel3',204 header: 'new',205 },206 });207 expect(nextState).toBe(state);208 });209 });210 describe('UPDATE_CHANNEL_PURPOSE', () => {211 test('should update channel purpose', () => {212 const state = deepFreeze({213 channelsInTeam: {},214 currentChannelId: '',215 groupsAssociatedToChannel: {},216 myMembers: {},217 stats: {},218 totalCount: 0,219 manuallyUnread: {},220 membersInChannel: {},221 channels: {222 channel1: {223 id: 'channel1',224 purpose: 'old',225 },226 channel2: {227 id: 'channel2',228 },229 },230 channelModerations: {},231 channelMemberCountsByGroup: {},232 });233 const nextState = channelsReducer(state, {234 type: ChannelTypes.UPDATE_CHANNEL_PURPOSE,235 data: {236 channelId: 'channel1',237 purpose: 'new',238 },239 });240 expect(nextState).not.toBe(state);241 expect(nextState.channels.channel1).toEqual({242 id: 'channel1',243 purpose: 'new',244 });245 expect(nextState.channels.channel2).toBe(state.channels.channel2);246 });247 test('should do nothing for a channel that is not loaded', () => {248 const state = deepFreeze({249 channelsInTeam: {},250 currentChannelId: '',251 groupsAssociatedToChannel: {},252 myMembers: {},253 stats: {},254 totalCount: 0,255 manuallyUnread: {},256 membersInChannel: {},257 channels: {258 channel1: {259 id: 'channel1',260 header: 'old',261 },262 channel2: {263 id: 'channel2',264 },265 },266 channelModerations: {},267 channelMemberCountsByGroup: {},268 });269 const nextState = channelsReducer(state, {270 type: ChannelTypes.UPDATE_CHANNEL_PURPOSE,271 data: {272 channelId: 'channel3',273 purpose: 'new',274 },275 });276 expect(nextState).toBe(state);277 });278 });279 describe('REMOVE_MEMBER_FROM_CHANNEL', () => {280 test('should remove the channel member', () => {281 const state = deepFreeze({282 channels: {},283 channelsInTeam: {},284 currentChannelId: '',285 groupsAssociatedToChannel: {},286 myMembers: {},287 stats: {},288 totalCount: 0,289 manuallyUnread: {},290 membersInChannel: {291 channel1: {292 memberId1: 'member-data-1',293 },294 channel2: {295 memberId2: 'member-data-2',296 },297 },298 channelModerations: {},299 channelMemberCountsByGroup: {},300 });301 const nextState = channelsReducer(state, {302 type: ChannelTypes.REMOVE_MEMBER_FROM_CHANNEL,303 data: {304 id: 'channel2',305 user_id: 'memberId2',306 },307 });308 expect(nextState.membersInChannel.channel2).toEqual({});309 expect(nextState.membersInChannel.channel1).toEqual(state.membersInChannel.channel1);310 });311 test('should work when channel member doesn\'t exist', () => {312 const state = deepFreeze({313 channels: {},314 channelsInTeam: {},315 currentChannelId: '',316 groupsAssociatedToChannel: {},317 myMembers: {},318 stats: {},319 totalCount: 0,320 manuallyUnread: {},321 membersInChannel: {322 channel1: {323 memberId1: 'member-data-1',324 },325 channel2: {326 memberId2: 'member-data-2',327 },328 },329 channelModerations: {},330 channelMemberCountsByGroup: {},331 });332 const nextState = channelsReducer(state, {333 type: ChannelTypes.REMOVE_MEMBER_FROM_CHANNEL,334 data: {335 id: 'channel2',336 user_id: 'test',337 },338 });339 expect(nextState).toEqual(state);340 });341 test('should work when channel doesn\'t exist', () => {342 const state = deepFreeze({343 channels: {},344 channelsInTeam: {},345 currentChannelId: '',346 groupsAssociatedToChannel: {},347 myMembers: {},348 stats: {},349 totalCount: 0,350 manuallyUnread: {},351 membersInChannel: {352 channel1: {353 memberId1: 'member-data-1',354 },355 channel2: {356 memberId2: 'member-data-2',357 },358 },359 channelModerations: {},360 channelMemberCountsByGroup: {},361 });362 const nextState = channelsReducer(state, {363 type: ChannelTypes.REMOVE_MEMBER_FROM_CHANNEL,364 data: {365 id: 'channel3',366 user_id: 'memberId2',367 },368 });369 expect(nextState).toEqual(state);370 });371 });372 describe('MANUALLY_UNREAD', () => {373 test('should mark channel as manually unread', () => {374 const state = deepFreeze({375 channel1: false,376 });377 const nextState = Reducers.manuallyUnread(state, {378 type: ChannelTypes.POST_UNREAD_SUCCESS,379 data: {channelId: 'channel1'},380 });381 expect(nextState.channel1).toBe(true);382 });383 test('should mark channel as manually unread even if undefined', () => {384 const state = deepFreeze({385 });386 const nextState = Reducers.manuallyUnread(state, {387 type: ChannelTypes.POST_UNREAD_SUCCESS,388 data: {channelId: 'channel1'},389 });390 expect(nextState.channel1).toBe(true);391 });392 test('should remove channel as manually unread', () => {393 const state = deepFreeze({394 channel1: true,395 });396 const nextState = Reducers.manuallyUnread(state, {397 type: ChannelTypes.REMOVE_MANUALLY_UNREAD,398 data: {channelId: 'channel1'},399 });400 expect(nextState.channel1).toBe(undefined);401 });402 test('shouldn\'t do nothing if channel was undefined', () => {403 const state = deepFreeze({404 });405 const nextState = Reducers.manuallyUnread(state, {406 type: ChannelTypes.REMOVE_MANUALLY_UNREAD,407 data: {channelId: 'channel1'},408 });409 expect(nextState.channel1).toBe(undefined);410 });411 test('remove all marks if user logs out', () => {412 const state = deepFreeze({413 channel1: true,414 channel231: false,415 });416 const nextState = Reducers.manuallyUnread(state, {417 type: UserTypes.LOGOUT_SUCCESS,418 data: {},419 });420 expect(nextState.channel1).toBe(undefined);421 expect(nextState.channel231).toBe(undefined);422 });423 });424 describe('RECEIVED_CHANNELS', () => {425 test('should not remove current channel', () => {426 const state = deepFreeze({427 channelsInTeam: {},428 currentChannelId: '',429 groupsAssociatedToChannel: {},430 myMembers: {},431 stats: {},432 totalCount: 0,433 membersInChannel: {},434 channels: {435 channel1: {436 id: 'channel1',437 team_id: 'team',438 },439 channel2: {440 id: 'channel2',441 team_id: 'team',442 },443 channel3: {444 id: 'channel3',445 team_id: 'team',446 },447 },448 channelModerations: {},449 channelMemberCountsByGroup: {},450 });451 const nextState = channelsReducer(state, {452 type: ChannelTypes.RECEIVED_CHANNELS,453 currentChannelId: 'channel3',454 teamId: 'team',455 data: [{456 id: 'channel1',457 team_id: 'team',458 }],459 });460 expect(nextState).not.toBe(state);461 expect(nextState.channels.channel1).toEqual({462 id: 'channel1',463 team_id: 'team',464 });465 expect(nextState.channels.channel2).toEqual({466 id: 'channel2',467 team_id: 'team',468 });469 expect(nextState.channels.channel3).toEqual({470 id: 'channel3',471 team_id: 'team',472 });473 });474 });475 describe('RECEIVED_CHANNEL_MODERATIONS', () => {476 test('Should add new channel moderations', () => {477 const state = deepFreeze({478 channelsInTeam: {},479 currentChannelId: '',480 groupsAssociatedToChannel: {},481 myMembers: {},482 stats: {},483 totalCount: 0,484 membersInChannel: {},485 channels: {486 channel1: {487 id: 'channel1',488 team_id: 'team',489 },490 },491 channelModerations: {},492 channelMemberCountsByGroup: {},493 });494 const nextState = channelsReducer(state, {495 type: ChannelTypes.RECEIVED_CHANNEL_MODERATIONS,496 sync: true,497 currentChannelId: 'channel1',498 teamId: 'team',499 data: {500 channelId: 'channel1',501 moderations: [502 {503 name: Permissions.CHANNEL_MODERATED_PERMISSIONS.CREATE_POST,504 roles: {505 members: true,506 },507 },508 ],509 },510 });511 expect(nextState.channelModerations.channel1[0].name).toEqual(Permissions.CHANNEL_MODERATED_PERMISSIONS.CREATE_POST);512 expect(nextState.channelModerations.channel1[0].roles.members).toEqual(true);513 });514 test('Should replace existing channel moderations', () => {515 const state = deepFreeze({516 channelsInTeam: {},517 currentChannelId: '',518 groupsAssociatedToChannel: {},519 myMembers: {},520 stats: {},521 totalCount: 0,522 membersInChannel: {},523 channels: {524 channel1: {525 id: 'channel1',526 team_id: 'team',527 },528 },529 channelModerations: {530 channel1: [{531 name: Permissions.CHANNEL_MODERATED_PERMISSIONS.CREATE_POST,532 roles: {533 members: true,534 },535 }],536 },537 channelMemberCountsByGroup: {},538 });539 const nextState = channelsReducer(state, {540 type: ChannelTypes.RECEIVED_CHANNEL_MODERATIONS,541 sync: true,542 currentChannelId: 'channel1',543 teamId: 'team',544 data: {545 channelId: 'channel1',546 moderations: [547 {548 name: Permissions.CHANNEL_MODERATED_PERMISSIONS.CREATE_REACTIONS,549 roles: {550 members: true,551 guests: false,552 },553 },554 ],555 },556 });557 expect(nextState.channelModerations.channel1[0].name).toEqual(Permissions.CHANNEL_MODERATED_PERMISSIONS.CREATE_REACTIONS);558 expect(nextState.channelModerations.channel1[0].roles.members).toEqual(true);559 expect(nextState.channelModerations.channel1[0].roles.guests).toEqual(false);560 });561 });562 describe('RECEIVED_CHANNEL_MEMBER_COUNTS_BY_GROUP', () => {563 test('Should add new channel member counts', () => {564 const state = deepFreeze({565 channelsInTeam: {},566 currentChannelId: '',567 groupsAssociatedToChannel: {},568 myMembers: {},569 stats: {},570 totalCount: 0,571 membersInChannel: {},572 channels: {573 channel1: {574 id: 'channel1',575 team_id: 'team',576 },577 },578 channelModerations: {},579 channelMemberCountsByGroup: {},580 });581 const nextState = channelsReducer(state, {582 type: ChannelTypes.RECEIVED_CHANNEL_MEMBER_COUNTS_BY_GROUP,583 sync: true,584 currentChannelId: 'channel1',585 teamId: 'team',586 data: {587 channelId: 'channel1',588 memberCounts: [589 {590 group_id: 'group-1',591 channel_member_count: 1,592 channel_member_timezones_count: 1,593 },594 {595 group_id: 'group-2',596 channel_member_count: 999,597 channel_member_timezones_count: 131,598 },599 ],600 },601 });602 expect(nextState.channelMemberCountsByGroup.channel1['group-1'].channel_member_count).toEqual(1);603 expect(nextState.channelMemberCountsByGroup.channel1['group-1'].channel_member_timezones_count).toEqual(1);604 expect(nextState.channelMemberCountsByGroup.channel1['group-2'].channel_member_count).toEqual(999);605 expect(nextState.channelMemberCountsByGroup.channel1['group-2'].channel_member_timezones_count).toEqual(131);606 });607 test('Should replace existing channel member counts', () => {608 const state = deepFreeze({609 channelsInTeam: {},610 currentChannelId: '',611 groupsAssociatedToChannel: {},612 myMembers: {},613 stats: {},614 totalCount: 0,615 membersInChannel: {},616 channels: {617 channel1: {618 id: 'channel1',619 team_id: 'team',620 },621 },622 channelModerations: {},623 channelMemberCountsByGroup: {624 'group-1': {625 group_id: 'group-1',626 channel_member_count: 1,627 channel_member_timezones_count: 1,628 },629 'group-2': {630 group_id: 'group-2',631 channel_member_count: 999,632 channel_member_timezones_count: 131,633 },634 },635 });636 const nextState = channelsReducer(state, {637 type: ChannelTypes.RECEIVED_CHANNEL_MEMBER_COUNTS_BY_GROUP,638 sync: true,639 currentChannelId: 'channel1',640 teamId: 'team',641 data: {642 channelId: 'channel1',643 memberCounts: [644 {645 group_id: 'group-1',646 channel_member_count: 5,647 channel_member_timezones_count: 2,648 },649 {650 group_id: 'group-2',651 channel_member_count: 1002,652 channel_member_timezones_count: 133,653 },654 {655 group_id: 'group-3',656 channel_member_count: 12,657 channel_member_timezones_count: 13,658 },659 ],660 },661 });662 expect(nextState.channelMemberCountsByGroup.channel1['group-1'].channel_member_count).toEqual(5);663 expect(nextState.channelMemberCountsByGroup.channel1['group-1'].channel_member_timezones_count).toEqual(2);664 expect(nextState.channelMemberCountsByGroup.channel1['group-2'].channel_member_count).toEqual(1002);665 expect(nextState.channelMemberCountsByGroup.channel1['group-2'].channel_member_timezones_count).toEqual(133);666 expect(nextState.channelMemberCountsByGroup.channel1['group-3'].channel_member_count).toEqual(12);667 expect(nextState.channelMemberCountsByGroup.channel1['group-3'].channel_member_timezones_count).toEqual(13);668 });669 });...

Full Screen

Full Screen

Using AI Code Generation

copy

Full Screen

1var wptoolkit = require('wptoolkit');2var channel1 = new wptoolkit.channel1();3channel1.init(function(err) {4 if (err) {5 console.log('Error initializing channel1: ' + err);6 } else {7 channel1.setMode(1, function(err) {8 if (err) {9 console.log('Error setting mode: ' + err);10 } else {11 channel1.setPulseWidth(1, 1.5, function(err) {12 if (err) {13 console.log('Error setting pulse width: ' + err);14 } else {15 console.log('Channel 1 set to 1.5ms');16 }17 });18 }19 });20 }21});

Full Screen

Using AI Code Generation

copy

Full Screen

1var wptools = require('wptools');2var CHANNEL1 = wptools.channel('CHANNEL1');3CHANNEL1.getArticles(function (err, articles) {4 if (err) {5 console.log(err);6 return;7 }8 console.log(articles);9});10var wptools = require('wptools');11var CHANNEL2 = wptools.channel('CHANNEL2');12CHANNEL2.getArticles(function (err, articles) {13 if (err) {14 console.log(err);15 return;16 }17 console.log(articles);18});19var wptools = require('wptools');20var CHANNEL3 = wptools.channel('CHANNEL3');21CHANNEL3.getArticles(function (err, articles) {22 if (err) {23 console.log(err);24 return;25 }26 console.log(articles);27});28var wptools = require('wptools');29var CHANNEL4 = wptools.channel('CHANNEL4');30CHANNEL4.getArticles(function (err, articles) {31 if (err) {32 console.log(err);33 return;34 }35 console.log(articles);36});37var wptools = require('wptools');38var CHANNEL5 = wptools.channel('CHANNEL5');39CHANNEL5.getArticles(function (err, articles) {40 if (err) {41 console.log(err);42 return;43 }44 console.log(articles);45});46var wptools = require('wptools');47var CHANNEL6 = wptools.channel('CHANNEL6');48CHANNEL6.getArticles(function (err, articles) {49 if (err) {50 console.log(err);51 return;52 }53 console.log(articles);54});55var wptools = require('wptools');56var CHANNEL7 = wptools.channel('CHANNEL7');57CHANNEL7.getArticles(function (err, articles) {58 if (err) {59 console.log(err);60 return;61 }62 console.log(articles);63});64var wptools = require('wptools');

Full Screen

Using AI Code Generation

copy

Full Screen

1var wptoolkit = require('wptoolkit');2 success: function(data) {3 console.log(data);4 },5 error: function(err) {6 console.log(err);7 }8});9var wptoolkit = require('wptoolkit');10 success: function(data) {11 console.log(data);12 },13 error: function(err) {14 console.log(err);15 }16});17var wptoolkit = require('wptoolkit');18 success: function(data) {19 console.log(data);20 },21 error: function(err) {22 console.log(err);23 }24});25var wptoolkit = require('wptoolkit');26 success: function(data) {27 console.log(data);28 },29 error: function(err) {30 console.log(err);31 }32});33var wptoolkit = require('wptoolkit');34 success: function(data) {35 console.log(data);36 },37 error: function(err) {38 console.log(err);39 }40});

Full Screen

Using AI Code Generation

copy

Full Screen

1var wptoolkit = require("wptoolkit");2var channel1 = wptoolkit.channel1;3channel1.sendMessage("Hello World!", function (response) {4 console.log(response);5});6var wptoolkit = require("wptoolkit");7var channel2 = wptoolkit.channel2;8channel2.sendMessage("Hello World!", function (response) {9 console.log(response);10});11var wptoolkit = require("wptoolkit");12var channel3 = wptoolkit.channel3;13channel3.sendMessage("Hello World!", function (response) {14 console.log(response);15});16var wptoolkit = require("wptoolkit");17var channel4 = wptoolkit.channel4;18channel4.sendMessage("Hello World!", function (response) {19 console.log(response);20});21var wptoolkit = require("wptoolkit");22var channel5 = wptoolkit.channel5;23channel5.sendMessage("Hello World!", function (response) {24 console.log(response);25});26var wptoolkit = require("wptoolkit");27var channel6 = wptoolkit.channel6;28channel6.sendMessage("Hello World!", function (response) {29 console.log(response);30});31var wptoolkit = require("wptoolkit");32var channel7 = wptoolkit.channel7;33channel7.sendMessage("Hello World!", function

Full Screen

Using AI Code Generation

copy

Full Screen

1var request = require('request');2var cheerio = require('cheerio');3var fs = require('fs');4var async = require('async');5var request = require('request');6var cheerio = require('cheerio');7var fs = require('fs');8var async = require('async');9var request = require('request');10var cheerio = require('cheerio');11var fs = require('fs');12var async = require('async');13var request = require('request');14var cheerio = require('cheerio');15var fs = require('fs');16var async = require('async');17var request = require('request');18var cheerio = require('cheerio');19var fs = require('fs');20var async = require('async');21var request = require('request');22var cheerio = require('cheerio');23var fs = require('fs');24var async = require('async');25var request = require('request');26var cheerio = require('cheerio');27var fs = require('fs');28var async = require('async');29var request = require('request');30var cheerio = require('cheerio');31var fs = require('fs');32var async = require('async');

Full Screen

Using AI Code Generation

copy

Full Screen

1var wpt = require('webpagetest');2var options = {3};4var test = wpt(options);5 videoParams: {6 }7}, function (err, data) {8 if (err) return console.error(err);9 console.log('Test started: ' + data.data.testId);10 test.getTestResults(data.data.testId, function (err, data) {11 if (err) return console.error(err);12 console.log(data.data.median);13 console.log(data.data.median.firstView.SpeedIndex);14 });15});

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run wpt automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful