Support for creating New Groups
This commit is contained in:
parent
1934120e46
commit
5de4babc0d
56 changed files with 6222 additions and 526 deletions
|
@ -0,0 +1,196 @@
|
|||
// Copyright 2021 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { assert } from 'chai';
|
||||
import * as sinon from 'sinon';
|
||||
import { times } from 'lodash';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import { RowType } from '../../../components/ConversationList';
|
||||
import * as remoteConfig from '../../../RemoteConfig';
|
||||
import { ContactCheckboxDisabledReason } from '../../../components/conversationList/ContactCheckbox';
|
||||
|
||||
import { LeftPaneChooseGroupMembersHelper } from '../../../components/leftPane/LeftPaneChooseGroupMembersHelper';
|
||||
|
||||
describe('LeftPaneChooseGroupMembersHelper', () => {
|
||||
const defaults = {
|
||||
candidateContacts: [],
|
||||
cantAddContactForModal: undefined,
|
||||
isShowingRecommendedGroupSizeModal: false,
|
||||
isShowingMaximumGroupSizeModal: false,
|
||||
searchTerm: '',
|
||||
selectedContacts: [],
|
||||
};
|
||||
|
||||
const fakeContact = () => ({
|
||||
id: uuid(),
|
||||
isGroupV2Capable: true,
|
||||
title: uuid(),
|
||||
type: 'direct' as const,
|
||||
});
|
||||
|
||||
let sinonSandbox: sinon.SinonSandbox;
|
||||
|
||||
beforeEach(() => {
|
||||
sinonSandbox = sinon.createSandbox();
|
||||
|
||||
sinonSandbox
|
||||
.stub(remoteConfig, 'getValue')
|
||||
.withArgs('global.groupsv2.maxGroupSize')
|
||||
.returns('22')
|
||||
.withArgs('global.groupsv2.groupSizeHardLimit')
|
||||
.returns('33');
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
sinonSandbox.restore();
|
||||
});
|
||||
|
||||
describe('getRowCount', () => {
|
||||
it('returns 0 if there are no contacts', () => {
|
||||
assert.strictEqual(
|
||||
new LeftPaneChooseGroupMembersHelper({
|
||||
...defaults,
|
||||
candidateContacts: [],
|
||||
searchTerm: '',
|
||||
selectedContacts: [fakeContact()],
|
||||
}).getRowCount(),
|
||||
0
|
||||
);
|
||||
assert.strictEqual(
|
||||
new LeftPaneChooseGroupMembersHelper({
|
||||
...defaults,
|
||||
candidateContacts: [],
|
||||
searchTerm: 'foo bar',
|
||||
selectedContacts: [fakeContact()],
|
||||
}).getRowCount(),
|
||||
0
|
||||
);
|
||||
});
|
||||
|
||||
it('returns the number of candidate contacts + 2 if there are any', () => {
|
||||
assert.strictEqual(
|
||||
new LeftPaneChooseGroupMembersHelper({
|
||||
...defaults,
|
||||
candidateContacts: [fakeContact(), fakeContact()],
|
||||
searchTerm: '',
|
||||
selectedContacts: [fakeContact()],
|
||||
}).getRowCount(),
|
||||
4
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getRow', () => {
|
||||
it('returns undefined if there are no contacts', () => {
|
||||
assert.isUndefined(
|
||||
new LeftPaneChooseGroupMembersHelper({
|
||||
...defaults,
|
||||
candidateContacts: [],
|
||||
searchTerm: '',
|
||||
selectedContacts: [fakeContact()],
|
||||
}).getRow(0)
|
||||
);
|
||||
assert.isUndefined(
|
||||
new LeftPaneChooseGroupMembersHelper({
|
||||
...defaults,
|
||||
candidateContacts: [],
|
||||
searchTerm: '',
|
||||
selectedContacts: [fakeContact()],
|
||||
}).getRow(99)
|
||||
);
|
||||
assert.isUndefined(
|
||||
new LeftPaneChooseGroupMembersHelper({
|
||||
...defaults,
|
||||
candidateContacts: [],
|
||||
searchTerm: 'foo bar',
|
||||
selectedContacts: [fakeContact()],
|
||||
}).getRow(0)
|
||||
);
|
||||
});
|
||||
|
||||
it('returns a header, then the contacts, then a blank space if there are contacts', () => {
|
||||
const candidateContacts = [fakeContact(), fakeContact()];
|
||||
const helper = new LeftPaneChooseGroupMembersHelper({
|
||||
...defaults,
|
||||
candidateContacts,
|
||||
searchTerm: 'foo bar',
|
||||
selectedContacts: [candidateContacts[1]],
|
||||
});
|
||||
|
||||
assert.deepEqual(helper.getRow(0), {
|
||||
type: RowType.Header,
|
||||
i18nKey: 'contactsHeader',
|
||||
});
|
||||
assert.deepEqual(helper.getRow(1), {
|
||||
type: RowType.ContactCheckbox,
|
||||
contact: candidateContacts[0],
|
||||
isChecked: false,
|
||||
disabledReason: undefined,
|
||||
});
|
||||
assert.deepEqual(helper.getRow(2), {
|
||||
type: RowType.ContactCheckbox,
|
||||
contact: candidateContacts[1],
|
||||
isChecked: true,
|
||||
disabledReason: undefined,
|
||||
});
|
||||
assert.deepEqual(helper.getRow(3), { type: RowType.Blank });
|
||||
});
|
||||
|
||||
it("disables non-selected contact checkboxes if you've selected the maximum number of contacts", () => {
|
||||
const candidateContacts = times(50, () => fakeContact());
|
||||
const helper = new LeftPaneChooseGroupMembersHelper({
|
||||
...defaults,
|
||||
candidateContacts,
|
||||
searchTerm: 'foo bar',
|
||||
selectedContacts: candidateContacts.slice(1, 33),
|
||||
});
|
||||
|
||||
assert.deepEqual(helper.getRow(1), {
|
||||
type: RowType.ContactCheckbox,
|
||||
contact: candidateContacts[0],
|
||||
isChecked: false,
|
||||
disabledReason: ContactCheckboxDisabledReason.MaximumContactsSelected,
|
||||
});
|
||||
assert.deepEqual(helper.getRow(2), {
|
||||
type: RowType.ContactCheckbox,
|
||||
contact: candidateContacts[1],
|
||||
isChecked: true,
|
||||
disabledReason: undefined,
|
||||
});
|
||||
});
|
||||
|
||||
it("disables contacts that aren't GV2-capable, unless they are already selected somehow", () => {
|
||||
const candidateContacts = [
|
||||
{ ...fakeContact(), isGroupV2Capable: false },
|
||||
{ ...fakeContact(), isGroupV2Capable: undefined },
|
||||
{ ...fakeContact(), isGroupV2Capable: false },
|
||||
];
|
||||
|
||||
const helper = new LeftPaneChooseGroupMembersHelper({
|
||||
...defaults,
|
||||
candidateContacts,
|
||||
searchTerm: 'foo bar',
|
||||
selectedContacts: [candidateContacts[2]],
|
||||
});
|
||||
|
||||
assert.deepEqual(helper.getRow(1), {
|
||||
type: RowType.ContactCheckbox,
|
||||
contact: candidateContacts[0],
|
||||
isChecked: false,
|
||||
disabledReason: ContactCheckboxDisabledReason.NotCapable,
|
||||
});
|
||||
assert.deepEqual(helper.getRow(2), {
|
||||
type: RowType.ContactCheckbox,
|
||||
contact: candidateContacts[1],
|
||||
isChecked: false,
|
||||
disabledReason: ContactCheckboxDisabledReason.NotCapable,
|
||||
});
|
||||
assert.deepEqual(helper.getRow(3), {
|
||||
type: RowType.ContactCheckbox,
|
||||
contact: candidateContacts[2],
|
||||
isChecked: true,
|
||||
disabledReason: undefined,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -2,9 +2,11 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { assert } from 'chai';
|
||||
import * as sinon from 'sinon';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import { RowType } from '../../../components/ConversationList';
|
||||
import { FindDirection } from '../../../components/leftPane/LeftPaneHelper';
|
||||
import * as remoteConfig from '../../../RemoteConfig';
|
||||
|
||||
import { LeftPaneComposeHelper } from '../../../components/leftPane/LeftPaneComposeHelper';
|
||||
|
||||
|
@ -15,8 +17,48 @@ describe('LeftPaneComposeHelper', () => {
|
|||
type: 'direct' as const,
|
||||
});
|
||||
|
||||
let sinonSandbox: sinon.SinonSandbox;
|
||||
let remoteConfigStub: sinon.SinonStub;
|
||||
|
||||
beforeEach(() => {
|
||||
sinonSandbox = sinon.createSandbox();
|
||||
|
||||
remoteConfigStub = sinonSandbox
|
||||
.stub(remoteConfig, 'isEnabled')
|
||||
.withArgs('desktop.storage')
|
||||
.returns(true)
|
||||
.withArgs('desktop.storageWrite2')
|
||||
.returns(true);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
sinonSandbox.restore();
|
||||
});
|
||||
|
||||
describe('getRowCount', () => {
|
||||
it('returns the number of contacts if not searching for a phone number', () => {
|
||||
it('returns 1 (for the "new group" button) if not searching and there are no contacts', () => {
|
||||
assert.strictEqual(
|
||||
new LeftPaneComposeHelper({
|
||||
composeContacts: [],
|
||||
regionCode: 'US',
|
||||
searchTerm: '',
|
||||
}).getRowCount(),
|
||||
1
|
||||
);
|
||||
});
|
||||
|
||||
it('returns the number of contacts + 2 (for the "new group" button and header) if not searching', () => {
|
||||
assert.strictEqual(
|
||||
new LeftPaneComposeHelper({
|
||||
composeContacts: [fakeContact(), fakeContact()],
|
||||
regionCode: 'US',
|
||||
searchTerm: '',
|
||||
}).getRowCount(),
|
||||
4
|
||||
);
|
||||
});
|
||||
|
||||
it('returns the number of contacts if searching, but not for a phone number', () => {
|
||||
assert.strictEqual(
|
||||
new LeftPaneComposeHelper({
|
||||
composeContacts: [],
|
||||
|
@ -29,26 +71,50 @@ describe('LeftPaneComposeHelper', () => {
|
|||
new LeftPaneComposeHelper({
|
||||
composeContacts: [fakeContact(), fakeContact()],
|
||||
regionCode: 'US',
|
||||
searchTerm: '',
|
||||
searchTerm: 'foo bar',
|
||||
}).getRowCount(),
|
||||
2
|
||||
);
|
||||
});
|
||||
|
||||
it('returns the number of contacts + 1 if searching for a phone number', () => {
|
||||
it('returns 1 (for the "Start new conversation" button) if searching for a phone number with no contacts', () => {
|
||||
assert.strictEqual(
|
||||
new LeftPaneComposeHelper({
|
||||
composeContacts: [],
|
||||
regionCode: 'US',
|
||||
searchTerm: '+16505551234',
|
||||
}).getRowCount(),
|
||||
1
|
||||
);
|
||||
});
|
||||
|
||||
it('returns the number of contacts + 2 (for the "Start new conversation" button and header) if searching for a phone number', () => {
|
||||
assert.strictEqual(
|
||||
new LeftPaneComposeHelper({
|
||||
composeContacts: [fakeContact(), fakeContact()],
|
||||
regionCode: 'US',
|
||||
searchTerm: '+16505551234',
|
||||
}).getRowCount(),
|
||||
3
|
||||
4
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getRow', () => {
|
||||
it('returns each contact as a row if not searching for a phone number', () => {
|
||||
it('returns a "new group" button if not searching and there are no contacts', () => {
|
||||
const helper = new LeftPaneComposeHelper({
|
||||
composeContacts: [],
|
||||
regionCode: 'US',
|
||||
searchTerm: '',
|
||||
});
|
||||
|
||||
assert.deepEqual(helper.getRow(0), {
|
||||
type: RowType.CreateNewGroup,
|
||||
});
|
||||
assert.isUndefined(helper.getRow(1));
|
||||
});
|
||||
|
||||
it('returns a "new group" button, a header, and contacts if not searching', () => {
|
||||
const composeContacts = [fakeContact(), fakeContact()];
|
||||
const helper = new LeftPaneComposeHelper({
|
||||
composeContacts,
|
||||
|
@ -56,6 +122,72 @@ describe('LeftPaneComposeHelper', () => {
|
|||
searchTerm: '',
|
||||
});
|
||||
|
||||
assert.deepEqual(helper.getRow(0), {
|
||||
type: RowType.CreateNewGroup,
|
||||
});
|
||||
assert.deepEqual(helper.getRow(1), {
|
||||
type: RowType.Header,
|
||||
i18nKey: 'contactsHeader',
|
||||
});
|
||||
assert.deepEqual(helper.getRow(2), {
|
||||
type: RowType.Contact,
|
||||
contact: composeContacts[0],
|
||||
});
|
||||
assert.deepEqual(helper.getRow(3), {
|
||||
type: RowType.Contact,
|
||||
contact: composeContacts[1],
|
||||
});
|
||||
});
|
||||
|
||||
it("doesn't let you create new groups if storage service write is disabled", () => {
|
||||
remoteConfigStub
|
||||
.withArgs('desktop.storage')
|
||||
.returns(false)
|
||||
.withArgs('desktop.storageWrite2')
|
||||
.returns(false);
|
||||
|
||||
assert.isUndefined(
|
||||
new LeftPaneComposeHelper({
|
||||
composeContacts: [],
|
||||
regionCode: 'US',
|
||||
searchTerm: '',
|
||||
}).getRow(0)
|
||||
);
|
||||
|
||||
remoteConfigStub
|
||||
.withArgs('desktop.storage')
|
||||
.returns(true)
|
||||
.withArgs('desktop.storageWrite2')
|
||||
.returns(false);
|
||||
|
||||
assert.isUndefined(
|
||||
new LeftPaneComposeHelper({
|
||||
composeContacts: [],
|
||||
regionCode: 'US',
|
||||
searchTerm: '',
|
||||
}).getRow(0)
|
||||
);
|
||||
});
|
||||
|
||||
it('returns no rows if searching and there are no results', () => {
|
||||
const helper = new LeftPaneComposeHelper({
|
||||
composeContacts: [],
|
||||
regionCode: 'US',
|
||||
searchTerm: 'foo bar',
|
||||
});
|
||||
|
||||
assert.isUndefined(helper.getRow(0));
|
||||
assert.isUndefined(helper.getRow(1));
|
||||
});
|
||||
|
||||
it('returns one row per contact if searching', () => {
|
||||
const composeContacts = [fakeContact(), fakeContact()];
|
||||
const helper = new LeftPaneComposeHelper({
|
||||
composeContacts,
|
||||
regionCode: 'US',
|
||||
searchTerm: 'foo bar',
|
||||
});
|
||||
|
||||
assert.deepEqual(helper.getRow(0), {
|
||||
type: RowType.Contact,
|
||||
contact: composeContacts[0],
|
||||
|
@ -66,7 +198,21 @@ describe('LeftPaneComposeHelper', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('returns a "start new conversation" row if searching for a phone number', () => {
|
||||
it('returns a "start new conversation" row if searching for a phone number and there are no results', () => {
|
||||
const helper = new LeftPaneComposeHelper({
|
||||
composeContacts: [],
|
||||
regionCode: 'US',
|
||||
searchTerm: '+16505551234',
|
||||
});
|
||||
|
||||
assert.deepEqual(helper.getRow(0), {
|
||||
type: RowType.StartNewConversation,
|
||||
phoneNumber: '+16505551234',
|
||||
});
|
||||
assert.isUndefined(helper.getRow(1));
|
||||
});
|
||||
|
||||
it('returns a "start new conversation" row, a header, and contacts if searching for a phone number', () => {
|
||||
const composeContacts = [fakeContact(), fakeContact()];
|
||||
const helper = new LeftPaneComposeHelper({
|
||||
composeContacts,
|
||||
|
@ -79,10 +225,14 @@ describe('LeftPaneComposeHelper', () => {
|
|||
phoneNumber: '+16505551234',
|
||||
});
|
||||
assert.deepEqual(helper.getRow(1), {
|
||||
type: RowType.Header,
|
||||
i18nKey: 'contactsHeader',
|
||||
});
|
||||
assert.deepEqual(helper.getRow(2), {
|
||||
type: RowType.Contact,
|
||||
contact: composeContacts[0],
|
||||
});
|
||||
assert.deepEqual(helper.getRow(2), {
|
||||
assert.deepEqual(helper.getRow(3), {
|
||||
type: RowType.Contact,
|
||||
contact: composeContacts[1],
|
||||
});
|
||||
|
@ -120,7 +270,7 @@ describe('LeftPaneComposeHelper', () => {
|
|||
});
|
||||
|
||||
describe('shouldRecomputeRowHeights', () => {
|
||||
it('always returns false because row heights are constant', () => {
|
||||
it('returns false if going from "no header" to "no header"', () => {
|
||||
const helper = new LeftPaneComposeHelper({
|
||||
composeContacts: [fakeContact(), fakeContact()],
|
||||
regionCode: 'US',
|
||||
|
@ -130,15 +280,79 @@ describe('LeftPaneComposeHelper', () => {
|
|||
assert.isFalse(
|
||||
helper.shouldRecomputeRowHeights({
|
||||
composeContacts: [fakeContact()],
|
||||
regionCode: 'US',
|
||||
searchTerm: 'foo bar',
|
||||
})
|
||||
);
|
||||
assert.isFalse(
|
||||
helper.shouldRecomputeRowHeights({
|
||||
composeContacts: [fakeContact(), fakeContact(), fakeContact()],
|
||||
regionCode: 'US',
|
||||
searchTerm: 'bing bong',
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('returns false if going from "has header" to "has header"', () => {
|
||||
const helper = new LeftPaneComposeHelper({
|
||||
composeContacts: [fakeContact(), fakeContact()],
|
||||
regionCode: 'US',
|
||||
searchTerm: '',
|
||||
});
|
||||
|
||||
assert.isFalse(
|
||||
helper.shouldRecomputeRowHeights({
|
||||
composeContacts: [fakeContact()],
|
||||
regionCode: 'US',
|
||||
searchTerm: '',
|
||||
})
|
||||
);
|
||||
assert.isFalse(
|
||||
helper.shouldRecomputeRowHeights({
|
||||
composeContacts: [fakeContact()],
|
||||
regionCode: 'US',
|
||||
searchTerm: '+16505559876',
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('returns true if going from "no header" to "has header"', () => {
|
||||
const helper = new LeftPaneComposeHelper({
|
||||
composeContacts: [fakeContact(), fakeContact()],
|
||||
regionCode: 'US',
|
||||
searchTerm: 'foo bar',
|
||||
});
|
||||
|
||||
assert.isTrue(
|
||||
helper.shouldRecomputeRowHeights({
|
||||
composeContacts: [fakeContact(), fakeContact()],
|
||||
regionCode: 'US',
|
||||
searchTerm: '',
|
||||
})
|
||||
);
|
||||
assert.isTrue(
|
||||
helper.shouldRecomputeRowHeights({
|
||||
composeContacts: [fakeContact(), fakeContact()],
|
||||
regionCode: 'US',
|
||||
searchTerm: '+16505551234',
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('returns true if going from "has header" to "no header"', () => {
|
||||
const helper = new LeftPaneComposeHelper({
|
||||
composeContacts: [fakeContact(), fakeContact()],
|
||||
regionCode: 'US',
|
||||
searchTerm: '',
|
||||
});
|
||||
|
||||
assert.isTrue(
|
||||
helper.shouldRecomputeRowHeights({
|
||||
composeContacts: [fakeContact(), fakeContact()],
|
||||
regionCode: 'US',
|
||||
searchTerm: 'foo bar',
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
// Copyright 2021 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { assert } from 'chai';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import { RowType } from '../../../components/ConversationList';
|
||||
|
||||
import { LeftPaneSetGroupMetadataHelper } from '../../../components/leftPane/LeftPaneSetGroupMetadataHelper';
|
||||
|
||||
describe('LeftPaneSetGroupMetadataHelper', () => {
|
||||
const fakeContact = () => ({
|
||||
id: uuid(),
|
||||
title: uuid(),
|
||||
type: 'direct' as const,
|
||||
});
|
||||
|
||||
describe('getRowCount', () => {
|
||||
it('returns 0 if there are no contacts', () => {
|
||||
assert.strictEqual(
|
||||
new LeftPaneSetGroupMetadataHelper({
|
||||
groupAvatar: undefined,
|
||||
groupName: '',
|
||||
hasError: false,
|
||||
isCreating: false,
|
||||
selectedContacts: [],
|
||||
}).getRowCount(),
|
||||
0
|
||||
);
|
||||
});
|
||||
|
||||
it('returns the number of candidate contacts + 2 if there are any', () => {
|
||||
assert.strictEqual(
|
||||
new LeftPaneSetGroupMetadataHelper({
|
||||
groupAvatar: undefined,
|
||||
groupName: '',
|
||||
hasError: false,
|
||||
isCreating: false,
|
||||
selectedContacts: [fakeContact(), fakeContact()],
|
||||
}).getRowCount(),
|
||||
4
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getRow', () => {
|
||||
it('returns undefined if there are no contacts', () => {
|
||||
assert.isUndefined(
|
||||
new LeftPaneSetGroupMetadataHelper({
|
||||
groupAvatar: undefined,
|
||||
groupName: '',
|
||||
hasError: false,
|
||||
isCreating: false,
|
||||
selectedContacts: [],
|
||||
}).getRow(0)
|
||||
);
|
||||
});
|
||||
|
||||
it('returns a header, then the contacts, then a blank space if there are contacts', () => {
|
||||
const selectedContacts = [fakeContact(), fakeContact()];
|
||||
const helper = new LeftPaneSetGroupMetadataHelper({
|
||||
groupAvatar: undefined,
|
||||
groupName: '',
|
||||
hasError: false,
|
||||
isCreating: false,
|
||||
selectedContacts,
|
||||
});
|
||||
|
||||
assert.deepEqual(helper.getRow(0), {
|
||||
type: RowType.Header,
|
||||
i18nKey: 'setGroupMetadata__members-header',
|
||||
});
|
||||
assert.deepEqual(helper.getRow(1), {
|
||||
type: RowType.Contact,
|
||||
contact: selectedContacts[0],
|
||||
isClickable: false,
|
||||
});
|
||||
assert.deepEqual(helper.getRow(2), {
|
||||
type: RowType.Contact,
|
||||
contact: selectedContacts[1],
|
||||
isClickable: false,
|
||||
});
|
||||
assert.deepEqual(helper.getRow(3), { type: RowType.Blank });
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue