Skip to content

Commit ce5d129

Browse files
authored
Merge pull request #2120 from MoveOnOrg/stage-main-12
stage-main 12.0 release candidate
2 parents 06f743f + e66c058 commit ce5d129

File tree

147 files changed

+6534
-3092
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

147 files changed

+6534
-3092
lines changed

.env.example

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,8 @@ NEXMO_API_KEY=
3232
NEXMO_API_SECRET=
3333
TWILIO_ACCOUNT_SID=
3434
TWILIO_AUTH_TOKEN=
35-
TWILIO_MESSAGE_CALLBACK_URL=
3635
TWILIO_MESSAGE_SERVICE_SID=
3736
EXPERIMENTAL_TWILIO_PER_CAMPAIGN_MESSAGING_SERVICE=false
38-
TWILIO_STATUS_CALLBACK_URL=
3937
TWILIO_SQS_QUEUE_URL=
4038
PHONE_NUMBER_COUNTRY=US
4139
ROLLBAR_CLIENT_TOKEN=

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Spoke is an open source text-distribution tool for organizations to mobilize sup
77

88
Spoke was created by Saikat Chakrabarti and Sheena Pakanati, and is now maintained by MoveOn.org.
99

10-
The latest version is [11.1](https://github.com/MoveOnOrg/Spoke/tree/v11.1) (see [release notes](https://github.com/MoveOnOrg/Spoke/blob/main/docs/RELEASE_NOTES.md#v111))
10+
The latest version is [12.0](https://github.com/MoveOnOrg/Spoke/tree/v12.0) (see [release notes](https://github.com/MoveOnOrg/Spoke/blob/main/docs/RELEASE_NOTES.md#v120))
1111

1212

1313
## Setting up Spoke
@@ -24,7 +24,7 @@ Want to know more?
2424
### Quick Start with Heroku
2525
This version of Spoke suitable for testing and, potentially, for small campaigns. This won't cost any money and will not support production(aka large-scale) usage. It's a great way to practice deploying Spoke or see it in action.
2626

27-
<a href="https://heroku.com/deploy?template=https://github.com/MoveOnOrg/Spoke/tree/v11.1">
27+
<a href="https://heroku.com/deploy?template=https://github.com/MoveOnOrg/Spoke/tree/v12.0">
2828

2929
<img src="https://www.herokucdn.com/deploy/button.svg" alt="Deploy">
3030
</a>

__test__/TexterStats.test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ describe("TexterStats (Non-dynamic campaign)", () => {
6565
<TexterStats campaign={campaign} organizationId="1" />
6666
);
6767
expect(stats.text()).toEqual(
68-
"Test Tester <Link />19%<Link />  |  <Link />  |  <Link />Someone Else (Suspended) <Link />99%<Link />  |  <Link />  |  <Link />"
68+
"Test Tester 19%Sweep conversations  |  View conversations in Message Review  |  Unmessaged: 193Someone Else (Suspended) 99%Sweep conversations  |  View conversations in Message Review  |  Unmessaged: 4"
6969
);
7070
});
7171

@@ -85,7 +85,7 @@ describe("TexterStats (Dynamic campaign)", () => {
8585
it("contains the right text", () => {
8686
const stats = shallow(<TexterStats campaign={campaignDynamic} />);
8787
expect(stats.text()).toEqual(
88-
"Test Tester <Link />45 initial messages sent. <Link />  |  <Link />  |  <Link />Someone Else (Suspended) <Link />541 initial messages sent. <Link />  |  <Link />  |  <Link />"
88+
"Test Tester 45 initial messages sent. Sweep conversations  |  View conversations in Message Review  |  Unmessaged: 193Someone Else (Suspended) 541 initial messages sent. Sweep conversations  |  View conversations in Message Review  |  Unmessaged: 4"
8989
);
9090
});
9191
});

__test__/TopNav.test.js

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,37 @@ import React from "react";
22
import { shallow } from "enzyme";
33
import { StyleSheetTestUtils } from "aphrodite";
44
import IconButton from "@material-ui/core/IconButton";
5-
import TopNav from "../src/components/TopNav";
5+
import { TopNavBase as TopNav } from "../src/components/TopNav";
6+
import UserMenu from "../src/containers/UserMenu";
7+
import { muiTheme } from "./test_helpers";
68

79
describe("TopNav", () => {
810
it("can render only title", () => {
9-
const nav = shallow(<TopNav title="Welcome to my website" />);
10-
expect(nav.text()).toEqual(
11-
"Welcome to my website<Apollo(withRouter(UserMenu)) />"
11+
const nav = shallow(
12+
<TopNav muiTheme={muiTheme} title="Welcome to my website" />
1213
);
14+
expect(nav.text()).toContain("Welcome to my website");
1315
expect(nav.find("Link").length).toBe(0);
1416
});
1517

1618
it("can render Link to go back", () => {
1719
const link = shallow(
18-
<TopNav title="Welcome" backToURL="/admin/1/campaigns" />
20+
<TopNav
21+
title="Welcome"
22+
muiTheme={muiTheme}
23+
backToURL="/admin/1/campaigns"
24+
/>
1925
).find("Link");
2026
expect(link.length).toBe(1);
2127
expect(link.prop("to")).toBe("/admin/1/campaigns");
2228
expect(link.find(IconButton).length).toBe(1);
2329
});
2430

2531
it("renders UserMenu", () => {
26-
const nav = shallow(<TopNav title="Welcome to my website" />);
27-
expect(nav.find("Apollo(withRouter(UserMenu))").length).toBe(1);
32+
const nav = shallow(
33+
<TopNav muiTheme={muiTheme} title="Welcome to my website" />
34+
);
35+
expect(nav.find(UserMenu).length).toBe(1);
2836
});
2937
});
3038

__test__/components/AssignmentSummary.test.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@ import { StyleSheetTestUtils } from "aphrodite";
77
import each from "jest-each";
88
import { ApolloProvider } from "react-apollo";
99
import ApolloClientSingleton from "../../src/network/apollo-client-singleton";
10-
import { AssignmentSummary } from "../../src/components/AssignmentSummary";
10+
import { AssignmentSummaryBase as AssignmentSummary } from "../../src/components/AssignmentSummary";
1111
import Badge from "@material-ui/core/Badge";
1212
import Button from "@material-ui/core/Button";
1313
import CardContent from "@material-ui/core/CardContent";
1414
import CardHeader from "@material-ui/core/CardHeader";
15+
import { muiTheme } from "../test_helpers";
1516

1617
function getAssignment({ isDynamic = false, counts = {} }) {
1718
return {
@@ -39,6 +40,7 @@ describe("AssignmentSummary text", function t() {
3940
beforeEach(() => {
4041
this.summary = mount(
4142
<AssignmentSummary
43+
muiTheme={muiTheme}
4244
assignment={getAssignment({
4345
counts: {
4446
unmessagedCount: 1,
@@ -89,6 +91,7 @@ describe("AssignmentSummary actions inUSA and NOT AllowSendAll", () => {
8991
return mount(
9092
<ApolloProvider client={ApolloClientSingleton}>
9193
<AssignmentSummary
94+
muiTheme={muiTheme}
9295
assignment={getAssignment({
9396
isDynamic,
9497
counts: {
@@ -193,6 +196,7 @@ describe("AssignmentSummary NOT inUSA and AllowSendAll", () => {
193196
window.ALLOW_SEND_ALL = true;
194197
return mount(
195198
<AssignmentSummary
199+
muiTheme={muiTheme}
196200
assignment={getAssignment({
197201
isDynamic,
198202
counts: {
@@ -231,6 +235,7 @@ describe("AssignmentSummary NOT inUSA and AllowSendAll", () => {
231235
it('renders "Send later" when there is a badTimezoneCount', () => {
232236
const actions = mount(
233237
<AssignmentSummary
238+
muiTheme={muiTheme}
234239
assignment={getAssignment({
235240
counts: {
236241
unmessagedCount: 0,
@@ -276,6 +281,7 @@ describe("contacts filters", () => {
276281
AssignmentSummary.prototype.renderBadgedButton = mockRender;
277282
mount(
278283
<AssignmentSummary
284+
muiTheme={muiTheme}
279285
assignment={getAssignment({
280286
counts: {
281287
unmessagedCount: 1,
@@ -309,6 +315,7 @@ describe("contacts filters", () => {
309315
AssignmentSummary.prototype.renderBadgedButton = mockRender;
310316
mount(
311317
<AssignmentSummary
318+
muiTheme={muiTheme}
312319
assignment={getAssignment({
313320
counts: {
314321
unmessagedCount: 1,

__test__/components/CampaignCannedResponseForm.test.js

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33
*/
44
import React from "react";
55
import { mount } from "enzyme";
6-
import AutoComplete from "@material-ui/lab/Autocomplete";
76
import CampaignCannedResponseForm from "../../src/components/CampaignCannedResponseForm";
87
import { StyleSheetTestUtils } from "aphrodite";
8+
import ThemeContext from "../../src/containers/context/ThemeContext";
9+
import { muiTheme } from "../test_helpers";
910

1011
describe("CampaignCannedResponseForm component", () => {
1112
// given
@@ -15,7 +16,12 @@ describe("CampaignCannedResponseForm component", () => {
1516
id: 1,
1617
title: "Response1",
1718
text: "Response1 desc",
18-
tagIds: [1, 2]
19+
tagIds: [1, 2],
20+
answerActions: "fake-action",
21+
answerActionsData: JSON.stringify({
22+
label: "Test Property",
23+
value: { property: "test" }
24+
})
1925
},
2026
tags: [
2127
{
@@ -28,7 +34,16 @@ describe("CampaignCannedResponseForm component", () => {
2834
name: "Tag2",
2935
description: "Tag2Desc"
3036
}
31-
]
37+
],
38+
availableActions: [
39+
{
40+
name: "fake-action",
41+
clientChoiceData: [
42+
{ name: "Test Property", details: { property: "test" } }
43+
]
44+
}
45+
],
46+
muiTheme: muiTheme
3247
};
3348

3449
const props2 = {
@@ -45,13 +60,18 @@ describe("CampaignCannedResponseForm component", () => {
4560
name: "Tag2",
4661
description: "Tag2Desc"
4762
}
48-
]
63+
],
64+
muiTheme: muiTheme
4965
};
5066

5167
// when
5268
test("Renders form with correct fields and label for editing", () => {
5369
StyleSheetTestUtils.suppressStyleInjection();
54-
const wrapper = mount(<CampaignCannedResponseForm {...props1} />);
70+
const wrapper = mount(
71+
<ThemeContext.Provider value={{ muiTheme }}>
72+
<CampaignCannedResponseForm {...props1} />
73+
</ThemeContext.Provider>
74+
);
5575
expect(
5676
wrapper
5777
.find({ label: "Title" })
@@ -64,7 +84,12 @@ describe("CampaignCannedResponseForm component", () => {
6484
.find("button")
6585
.text()
6686
).toBe("Edit Response");
67-
expect(wrapper.find(AutoComplete).prop("value")).toEqual([
87+
expect(
88+
wrapper
89+
.find({ "data-test": "autocompleteTags" })
90+
.first()
91+
.prop("value")
92+
).toEqual([
6893
{
6994
id: 1,
7095
name: "Tag1",
@@ -76,11 +101,27 @@ describe("CampaignCannedResponseForm component", () => {
76101
description: "Tag2Desc"
77102
}
78103
]);
104+
expect(
105+
wrapper
106+
.find({ "data-test": "actionSelect" })
107+
.find("input")
108+
.prop("value")
109+
).toBe(props1.defaultValue.answerActions);
110+
expect(
111+
wrapper
112+
.find({ "data-test": "actionDataAutoComplete" })
113+
.find("input")
114+
.prop("value")
115+
).toEqual(JSON.parse(props1.defaultValue.answerActionsData).label);
79116
});
80117

81118
test("Renders form with correct fields and label for adding", () => {
82119
StyleSheetTestUtils.suppressStyleInjection();
83-
const wrapper = mount(<CampaignCannedResponseForm {...props2} />);
120+
const wrapper = mount(
121+
<ThemeContext.Provider value={{ muiTheme }}>
122+
<CampaignCannedResponseForm {...props2} />
123+
</ThemeContext.Provider>
124+
);
84125
expect(
85126
wrapper
86127
.find({ label: "Title" })

__test__/components/CampaignCannedResponsesForm.test.js

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import { CampaignCannedResponsesForm } from "../../src/components/CampaignCanned
77
import { StyleSheetTestUtils } from "aphrodite";
88
import IconButton from "@material-ui/core/IconButton";
99
import ListItemText from "@material-ui/core/ListItemText";
10+
import ThemeContext from "../../src/containers/context/ThemeContext";
11+
import { muiTheme } from "../test_helpers";
1012

1113
describe("CampaignCannedResponsesForm component", () => {
1214
// given
@@ -16,7 +18,9 @@ describe("CampaignCannedResponsesForm component", () => {
1618
id: 1,
1719
title: "Response1",
1820
text: "Response1 desc",
19-
tagIds: [1, 2]
21+
tagIds: [1, 2],
22+
answerActions: "fake-action",
23+
answerActionsData: JSON.stringify({ label: "Test Property" })
2024
}
2125
]
2226
};
@@ -38,16 +42,32 @@ describe("CampaignCannedResponsesForm component", () => {
3842
}
3943
};
4044

45+
const availableActions = [
46+
{
47+
name: "fake-action",
48+
displayName: "Fake Action"
49+
}
50+
];
51+
4152
StyleSheetTestUtils.suppressStyleInjection();
4253
const wrapper = mount(
43-
<CampaignCannedResponsesForm formValues={formValues} data={data} />
54+
<ThemeContext.Provider value={{ muiTheme }}>
55+
<CampaignCannedResponsesForm
56+
formValues={formValues}
57+
data={data}
58+
availableActions={availableActions}
59+
muiTheme={muiTheme}
60+
/>
61+
</ThemeContext.Provider>
4462
);
4563

4664
// when
4765

4866
test("Renders canned responses with correct text", () => {
4967
expect(wrapper.find(ListItemText).text()).toContain("Response1");
5068
expect(wrapper.find(ListItemText).text()).toContain("Response1 desc");
69+
expect(wrapper.find(ListItemText).text()).toContain("Fake Action");
70+
expect(wrapper.find(ListItemText).text()).toContain("Test Property");
5171
expect(wrapper.find("TagChips").prop("tagIds")).toEqual([1, 2]);
5272
expect(wrapper.find("TagChips").prop("tags")).toEqual([
5373
{
@@ -76,7 +96,9 @@ describe("CampaignCannedResponsesForm component", () => {
7696
id: 1,
7797
title: "Response1",
7898
text: "Response1 desc",
79-
tagIds: [1, 2]
99+
tagIds: [1, 2],
100+
answerActions: "fake-action",
101+
answerActionsData: JSON.stringify({ label: "Test Property" })
80102
});
81103
expect(cannedResponseForm.prop("formButtonText")).toBe("Edit Response");
82104
});

0 commit comments

Comments
 (0)