-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
211 additions
and
152 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
// Copyright 2020 Signal Messenger, LLC | ||
// SPDX-License-Identifier: AGPL-3.0-only | ||
|
||
import Fuse from 'fuse.js'; | ||
|
||
import { ConversationType } from '../state/ducks/conversations'; | ||
|
||
const FUSE_OPTIONS = { | ||
location: 0, | ||
shouldSort: true, | ||
threshold: 0, | ||
maxPatternLength: 32, | ||
minMatchCharLength: 1, | ||
tokenize: true, | ||
keys: ['name', 'firstName', 'profileName', 'title'], | ||
}; | ||
|
||
export class MemberRepository { | ||
private members: Array<ConversationType>; | ||
|
||
private fuse: Fuse<ConversationType>; | ||
|
||
constructor(members: Array<ConversationType> = []) { | ||
this.members = members; | ||
this.fuse = new Fuse<ConversationType>(this.members, FUSE_OPTIONS); | ||
} | ||
|
||
updateMembers(members: Array<ConversationType>): void { | ||
this.members = members; | ||
this.fuse = new Fuse(members, FUSE_OPTIONS); | ||
} | ||
|
||
getMembers(omit?: ConversationType): Array<ConversationType> { | ||
if (omit) { | ||
return this.members.filter(({ id }) => id !== omit.id); | ||
} | ||
|
||
return this.members; | ||
} | ||
|
||
getMemberById(id?: string): ConversationType | undefined { | ||
return id | ||
? this.members.find(({ id: memberId }) => memberId === id) | ||
: undefined; | ||
} | ||
|
||
getMemberByUuid(uuid?: string): ConversationType | undefined { | ||
return uuid | ||
? this.members.find(({ uuid: memberUuid }) => memberUuid === uuid) | ||
: undefined; | ||
} | ||
|
||
search(pattern: string, omit?: ConversationType): Array<ConversationType> { | ||
const results = this.fuse.search(`${pattern}`); | ||
|
||
if (omit) { | ||
return results.filter(({ id }) => id !== omit.id); | ||
} | ||
|
||
return results; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
// Copyright 2020 Signal Messenger, LLC | ||
// SPDX-License-Identifier: AGPL-3.0-only | ||
|
||
import { assert } from 'chai'; | ||
|
||
import { ConversationType } from '../../state/ducks/conversations'; | ||
import { MemberRepository } from '../../quill/memberRepository'; | ||
|
||
const memberMahershala: ConversationType = { | ||
id: '555444', | ||
uuid: 'abcdefg', | ||
title: 'Pal', | ||
firstName: 'Mahershala', | ||
profileName: 'Mr Ali', | ||
name: 'Friend', | ||
type: 'direct', | ||
lastUpdated: Date.now(), | ||
markedUnread: false, | ||
}; | ||
|
||
const memberShia: ConversationType = { | ||
id: '333222', | ||
uuid: 'hijklmno', | ||
title: 'Buddy', | ||
firstName: 'Shia', | ||
profileName: 'Sr LaBeouf', | ||
name: 'Duder', | ||
type: 'direct', | ||
lastUpdated: Date.now(), | ||
markedUnread: false, | ||
}; | ||
|
||
const members: Array<ConversationType> = [memberMahershala, memberShia]; | ||
|
||
const singleMember: ConversationType = { | ||
id: '666777', | ||
uuid: 'pqrstuv', | ||
title: 'The Guy', | ||
firstName: 'Jeff', | ||
profileName: 'Jr Klaus', | ||
name: 'Him', | ||
type: 'direct', | ||
lastUpdated: Date.now(), | ||
markedUnread: false, | ||
}; | ||
|
||
describe('MemberRepository', () => { | ||
describe('#updateMembers', () => { | ||
it('updates with given members', () => { | ||
const memberRepository = new MemberRepository(members); | ||
assert.deepEqual(memberRepository.getMembers(), members); | ||
|
||
const updatedMembers = [...members, singleMember]; | ||
memberRepository.updateMembers(updatedMembers); | ||
assert.deepEqual(memberRepository.getMembers(), updatedMembers); | ||
}); | ||
}); | ||
|
||
describe('#getMemberById', () => { | ||
it('returns undefined when there is no search id', () => { | ||
const memberRepository = new MemberRepository(members); | ||
assert.isUndefined(memberRepository.getMemberById()); | ||
}); | ||
|
||
it('returns a matched member', () => { | ||
const memberRepository = new MemberRepository(members); | ||
assert.isDefined(memberRepository.getMemberById('555444')); | ||
}); | ||
|
||
it('returns undefined when it does not have the member', () => { | ||
const memberRepository = new MemberRepository(members); | ||
assert.isUndefined(memberRepository.getMemberById('nope')); | ||
}); | ||
}); | ||
|
||
describe('#getMemberByUuid', () => { | ||
it('returns undefined when there is no search uuid', () => { | ||
const memberRepository = new MemberRepository(members); | ||
assert.isUndefined(memberRepository.getMemberByUuid()); | ||
}); | ||
|
||
it('returns a matched member', () => { | ||
const memberRepository = new MemberRepository(members); | ||
assert.isDefined(memberRepository.getMemberByUuid('abcdefg')); | ||
}); | ||
|
||
it('returns undefined when it does not have the member', () => { | ||
const memberRepository = new MemberRepository(members); | ||
assert.isUndefined(memberRepository.getMemberByUuid('nope')); | ||
}); | ||
}); | ||
|
||
describe('#search', () => { | ||
describe('given a prefix-matching string on last name', () => { | ||
it('returns the match', () => { | ||
const memberRepository = new MemberRepository(members); | ||
const results = memberRepository.search('a'); | ||
assert.deepEqual(results, [memberMahershala]); | ||
}); | ||
}); | ||
|
||
describe('given a prefix-matching string on first name', () => { | ||
it('returns the match', () => { | ||
const memberRepository = new MemberRepository(members); | ||
const results = memberRepository.search('ma'); | ||
assert.deepEqual(results, [memberMahershala]); | ||
}); | ||
}); | ||
|
||
describe('given a prefix-matching string on profile name', () => { | ||
it('returns the match', () => { | ||
const memberRepository = new MemberRepository(members); | ||
const results = memberRepository.search('sr'); | ||
assert.deepEqual(results, [memberShia]); | ||
}); | ||
}); | ||
|
||
describe('given a prefix-matching string on title', () => { | ||
it('returns the match', () => { | ||
const memberRepository = new MemberRepository(members); | ||
const results = memberRepository.search('d'); | ||
assert.deepEqual(results, [memberShia]); | ||
}); | ||
}); | ||
|
||
describe('given a match in the middle of a name', () => { | ||
it('returns zero matches', () => { | ||
const memberRepository = new MemberRepository(members); | ||
const results = memberRepository.search('e'); | ||
assert.deepEqual(results, []); | ||
}); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.