Skip to content

Commit 573daa0

Browse files
committed
Implement public actions to view newsletters
1 parent b8fdc03 commit 573daa0

File tree

8 files changed

+166
-17
lines changed

8 files changed

+166
-17
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
class NewslettersController < ApplicationController
2+
def index
3+
@newsletters = Newsletter.sent
4+
end
5+
6+
def show
7+
@newsletter = Newsletter.find(params[:id])
8+
end
9+
end

app/models/newsletter.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
class Newsletter < ApplicationRecord
22
validates :title, presence: true
33
validates :content, presence: true
4+
5+
scope :sent, -> { where.not(sent_at: nil).order(sent_at: :desc) }
46
end
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<div id="<%= dom_id newsletter %>" class="joy-border p-4">
2+
<%= basic_markdown (newsletter&.content || "").html_safe %>
3+
</div>

app/views/newsletters/index.html.erb

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<%= render Pages::Header.new(title: "Joy of Rails Newsletter") %>
2+
<div class="section-content container py-gap">
3+
<div class="only:inherit grid grid-row-mid">
4+
<h2>No newsletters have been sent yet!</h2>
5+
<div>
6+
<p>Coming soon ;)</p>
7+
</div>
8+
</div>
9+
<% @newsletters.each do |newsletter| %>
10+
<div id="dom_id(newsletter)">
11+
<h2><%= link_to newsletter.title, newsletter %></h2>
12+
<div>
13+
<p><%= time_tag newsletter.sent_at.to_date %></p>
14+
</div>
15+
</div>
16+
<% end %>
17+
</div>

app/views/newsletters/show.html.erb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<%= render Pages::Header.new(title: @newsletter.title, published_on: @newsletter.sent_at&.to_date) %>
2+
<div class="section-content container py-gap">
3+
<%= render @newsletter %>
4+
</div>

config/routes.rb

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,15 @@
1010
sitepress_root controller: :site
1111
sitepress_pages controller: :site
1212

13+
resources :newsletters, only: [:index, :show]
14+
1315
namespace :examples do
1416
resource :counters, only: [:show, :update, :destroy]
1517
resource :hello, only: [:show]
1618
resources :posts, only: [:index, :create, :new]
1719
end
1820
resources :examples, only: [:index, :show]
1921

20-
namespace :pwa do
21-
resource :installation_instructions, only: [:show]
22-
resources :web_pushes, only: [:create]
23-
end
24-
2522
resources :feed, only: [:index], format: "atom"
2623

2724
resources :color_schemes, only: [:index, :show]
@@ -35,6 +32,11 @@
3532
resource :syntax_highlight, only: [:show, :update]
3633
end
3734

35+
namespace :pwa do
36+
resource :installation_instructions, only: [:show]
37+
resources :web_pushes, only: [:create]
38+
end
39+
3840
namespace :users do
3941
resource :thank_you, only: [:show]
4042
resource :header_navigation, only: [:show]

spec/requests/admin/newsletters_spec.rb

Lines changed: 95 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,5 @@
11
require "rails_helper"
22

3-
# This spec was generated by rspec-rails when you ran the scaffold generator.
4-
# It demonstrates how one might use RSpec to test the controller code that
5-
# was generated by Rails when you ran the scaffold generator.
6-
#
7-
# It assumes that the implementation code is generated by the rails scaffold
8-
# generator. If you are using any extension libraries to generate different
9-
# controller code, this generated spec may or may not pass.
10-
#
11-
# It only uses APIs available in rails and/or rspec-rails. There are a number
12-
# of tools you can use to make these specs even more expressive, but we're
13-
# sticking to rails and rspec-rails APIs to keep things simple and stable.
14-
153
RSpec.describe "/admin/newsletters", type: :request do
164
let(:valid_attributes) { FactoryBot.attributes_for(:newsletter) }
175
let(:invalid_attributes) { {title: "", content: ""} }
@@ -110,6 +98,101 @@
11098
end
11199
end
112100

101+
describe "PATCH /deliver" do
102+
before do
103+
allow(PostmarkClient).to receive(:deliver_messages)
104+
end
105+
106+
context "with no parameters" do
107+
before do
108+
FactoryBot.create(:user, :confirmed, :subscribed, email: ApplicationMailer.test_recipients.first)
109+
FactoryBot.create_list(:user, 2, :confirmed, :subscribed)
110+
end
111+
112+
it "sends test email" do
113+
newsletter = FactoryBot.create(:newsletter)
114+
patch deliver_admin_newsletter_path(newsletter)
115+
perform_enqueued_jobs_and_subsequently_enqueued_jobs
116+
newsletter.reload
117+
expect(newsletter.sent_at).to be_blank
118+
expect(PostmarkClient).to have_received(:deliver_messages) do |messages|
119+
expect(messages.size).to eq(1)
120+
expect(messages.first.to).to eq(User.test_recipients.map(&:email))
121+
end
122+
end
123+
124+
it "redirects to the admin_newsletter" do
125+
newsletter = FactoryBot.create(:newsletter)
126+
patch deliver_admin_newsletter_path(newsletter)
127+
newsletter.reload
128+
expect(response).to redirect_to(admin_newsletter_path(newsletter))
129+
end
130+
end
131+
132+
context "with live parameter" do
133+
before do
134+
FactoryBot.create_list(:user, 2, :confirmed, :subscribed)
135+
end
136+
137+
it "sends emails to subscribers" do
138+
newsletter = FactoryBot.create(:newsletter)
139+
patch deliver_admin_newsletter_path(newsletter), params: {live: "true"}
140+
perform_enqueued_jobs_and_subsequently_enqueued_jobs
141+
newsletter.reload
142+
expect(newsletter.sent_at).to be_present
143+
expect(PostmarkClient).to have_received(:deliver_messages) do |messages|
144+
expect(messages.size).to eq(2)
145+
expect(messages.flat_map(&:to)).to eq(User.subscribers.map(&:email))
146+
end
147+
end
148+
149+
it "redirects to the admin_newsletter" do
150+
newsletter = FactoryBot.create(:newsletter)
151+
patch deliver_admin_newsletter_path(newsletter), params: {live: "true"}
152+
newsletter.reload
153+
expect(response).to redirect_to(admin_newsletter_path(newsletter))
154+
end
155+
end
156+
157+
context "with no recipients" do
158+
it "does not send any emails" do
159+
newsletter = FactoryBot.create(:newsletter)
160+
patch deliver_admin_newsletter_path(newsletter), params: {live: "true"}
161+
perform_enqueued_jobs_and_subsequently_enqueued_jobs
162+
newsletter.reload
163+
expect(PostmarkClient).not_to have_received(:deliver_messages)
164+
end
165+
166+
it "redirects to the admin_newsletter" do
167+
newsletter = FactoryBot.create(:newsletter)
168+
patch deliver_admin_newsletter_path(newsletter), params: {live: "true"}
169+
newsletter.reload
170+
expect(response).to redirect_to(admin_newsletter_path(newsletter))
171+
end
172+
end
173+
174+
context "newsletter is already sent" do
175+
before do
176+
FactoryBot.create_list(:user, 2, :subscribed)
177+
end
178+
179+
it "does not send any emails" do
180+
newsletter = FactoryBot.create(:newsletter)
181+
patch deliver_admin_newsletter_path(newsletter), params: {live: "true"}
182+
perform_enqueued_jobs_and_subsequently_enqueued_jobs
183+
newsletter.reload
184+
expect(PostmarkClient).not_to have_received(:deliver_messages)
185+
end
186+
187+
it "redirects to the admin_newsletter" do
188+
newsletter = FactoryBot.create(:newsletter)
189+
patch deliver_admin_newsletter_path(newsletter), params: {live: "true"}
190+
newsletter.reload
191+
expect(response).to redirect_to(admin_newsletter_path(newsletter))
192+
end
193+
end
194+
end
195+
113196
describe "DELETE /destroy" do
114197
it "destroys the requested admin_newsletter" do
115198
newsletter = FactoryBot.create(:newsletter)

spec/requests/newsletter_spec.rb

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
require "rails_helper"
2+
3+
RSpec.describe "/newsletters", type: :request do
4+
describe "GET /" do
5+
it "renders a successful response" do
6+
FactoryBot.create_list(:newsletter, 2)
7+
8+
get newsletters_path
9+
10+
expect(response).to be_successful
11+
end
12+
13+
it "renders a successful without newsletters" do
14+
get newsletters_path
15+
16+
expect(response).to be_successful
17+
end
18+
end
19+
20+
describe "GET /show" do
21+
it "renders a successful response" do
22+
newsletter = FactoryBot.create(:newsletter)
23+
24+
get newsletter_path(newsletter)
25+
26+
expect(response).to be_successful
27+
end
28+
end
29+
end

0 commit comments

Comments
 (0)