FEATURE: Cook drafts excerpt in user activity (#14315)

The previous excerpt was a simple truncated raw message. Starting with
this commit, the raw content of the draft is cooked and an excerpt is
extracted from it. The logic for extracting the excerpt mimics the the
`ExcerptParser` class, but does not implement all functionality, being
a much simpler implementation.

The two draft controllers have been merged into one and the /draft.json
route has been changed to /drafts.json to be consistent with the other
route names.
This commit is contained in:
Dan Ungureanu
2021-09-14 15:18:01 +03:00
committed by GitHub
parent dde66b9e16
commit f517b6997c
18 changed files with 438 additions and 437 deletions

View File

@ -3,55 +3,210 @@
require 'rails_helper'
describe DraftsController do
it 'requires you to be logged in' do
get "/drafts.json"
expect(response.status).to eq(403)
describe "#index" do
it 'requires you to be logged in' do
get "/drafts.json"
expect(response.status).to eq(403)
end
it 'returns correct stream length after adding a draft' do
user = sign_in(Fabricate(:user))
Draft.set(user, 'xxx', 0, '{}')
get "/drafts.json"
expect(response.status).to eq(200)
parsed = response.parsed_body
expect(response.parsed_body["drafts"].length).to eq(1)
end
it 'has empty stream after deleting last draft' do
user = sign_in(Fabricate(:user))
Draft.set(user, 'xxx', 0, '{}')
Draft.clear(user, 'xxx', 0)
get "/drafts.json"
expect(response.status).to eq(200)
expect(response.parsed_body["drafts"].length).to eq(0)
end
it 'does not include topic details when user cannot see topic' do
topic = Fabricate(:private_message_topic)
topic_user = topic.user
other_user = Fabricate(:user)
Draft.set(topic_user, "topic_#{topic.id}", 0, '{}')
Draft.set(other_user, "topic_#{topic.id}", 0, '{}')
sign_in(topic_user)
get "/drafts.json"
expect(response.status).to eq(200)
expect(response.parsed_body["drafts"].first["title"]).to eq(topic.title)
sign_in(other_user)
get "/drafts.json"
expect(response.status).to eq(200)
expect(response.parsed_body["drafts"].first["title"]).to eq(nil)
end
end
it 'returns correct stream length after adding a draft' do
user = sign_in(Fabricate(:user))
Draft.set(user, 'xxx', 0, '{}')
get "/drafts.json", params: { username: user.username }
expect(response.status).to eq(200)
parsed = response.parsed_body
expect(parsed["drafts"].length).to eq(1)
describe "#show" do
it "returns a draft if requested" do
user = sign_in(Fabricate(:user))
Draft.set(user, 'hello', 0, 'test')
get "/drafts/hello.json"
expect(response.status).to eq(200)
expect(response.parsed_body['draft']).to eq('test')
end
end
it 'has empty stream after deleting last draft' do
user = sign_in(Fabricate(:user))
Draft.set(user, 'xxx', 0, '{}')
Draft.clear(user, 'xxx', 0)
get "/drafts.json", params: { username: user.username }
expect(response.status).to eq(200)
parsed = response.parsed_body
expect(parsed["drafts"].length).to eq(0)
describe "#create" do
it 'requires you to be logged in' do
post "/drafts.json"
expect(response.status).to eq(403)
end
it 'saves a draft' do
user = sign_in(Fabricate(:user))
post "/drafts.json", params: {
draft_key: 'xyz',
data: { my: "data" }.to_json,
sequence: 0
}
expect(response.status).to eq(200)
expect(Draft.get(user, 'xyz', 0)).to eq(%q({"my":"data"}))
end
it "returns 404 when the key is missing" do
sign_in(Fabricate(:user))
post "/drafts.json", params: { data: { my: "data" }.to_json, sequence: 0 }
expect(response.status).to eq(404)
end
it 'checks for an conflict on update' do
user = sign_in(Fabricate(:user))
post = Fabricate(:post, user: user)
post "/drafts.json", params: {
draft_key: "topic",
sequence: 0,
data: {
postId: post.id,
originalText: post.raw,
action: "edit"
}.to_json
}
expect(response.status).to eq(200)
expect(response.parsed_body['conflict_user']).to eq(nil)
post "/drafts.json", params: {
draft_key: "topic",
sequence: 0,
data: {
postId: post.id,
originalText: "something else",
action: "edit"
}.to_json
}
expect(response.status).to eq(200)
expect(response.parsed_body['conflict_user']['id']).to eq(post.last_editor.id)
expect(response.parsed_body['conflict_user']).to include('avatar_template')
end
it 'cant trivially resolve conflicts without interaction' do
user = sign_in(Fabricate(:user))
DraftSequence.next!(user, "abc")
post "/drafts.json", params: {
draft_key: "abc",
sequence: 0,
data: { a: "test" }.to_json,
owner: "abcdefg"
}
expect(response.status).to eq(200)
expect(response.parsed_body["draft_sequence"]).to eq(1)
end
it 'has a clean protocol for ownership handover' do
user = sign_in(Fabricate(:user))
post "/drafts.json", params: {
draft_key: "abc",
sequence: 0,
data: { a: "test" }.to_json,
owner: "abcdefg"
}
expect(response.status).to eq(200)
expect(response.parsed_body["draft_sequence"]).to eq(0)
post "/drafts.json", params: {
draft_key: "abc",
sequence: 0,
data: { b: "test" }.to_json,
owner: "hijklmnop"
}
expect(response.status).to eq(200)
expect(response.parsed_body["draft_sequence"]).to eq(1)
expect(DraftSequence.current(user, "abc")).to eq(1)
post "/drafts.json", params: {
draft_key: "abc",
sequence: 1,
data: { c: "test" }.to_json,
owner: "hijklmnop"
}
expect(response.status).to eq(200)
expect(response.parsed_body["draft_sequence"]).to eq(2)
post "/drafts.json", params: {
draft_key: "abc",
sequence: 2,
data: { c: "test" }.to_json,
owner: "abc"
}
expect(response.status).to eq(200)
expect(response.parsed_body["draft_sequence"]).to eq(3)
end
it 'raises an error for out-of-sequence draft setting' do
user = sign_in(Fabricate(:user))
seq = DraftSequence.next!(user, "abc")
Draft.set(user, "abc", seq, { b: "test" }.to_json)
post "/drafts.json", params: {
draft_key: "abc",
sequence: seq - 1,
data: { a: "test" }.to_json
}
expect(response.status).to eq(409)
post "/drafts.json", params: {
draft_key: "abc",
sequence: seq + 1,
data: { a: "test" }.to_json
}
expect(response.status).to eq(409)
end
end
it 'does not let a user see drafts stream of another user' do
user_b = Fabricate(:user)
Draft.set(user_b, 'xxx', 0, '{}')
sign_in(Fabricate(:user))
get "/drafts.json", params: { username: user_b.username }
expect(response.status).to eq(403)
end
it 'does not include topic details when user cannot see topic' do
topic = Fabricate(:private_message_topic)
topic_user = topic.user
other_user = Fabricate(:user)
Draft.set(topic_user, "topic_#{topic.id}", 0, '{}')
Draft.set(other_user, "topic_#{topic.id}", 0, '{}')
sign_in(topic_user)
get "/drafts.json", params: { username: topic_user.username }
expect(response.status).to eq(200)
parsed = response.parsed_body
expect(parsed["drafts"].first["title"]).to eq(topic.title)
sign_in(other_user)
get "/drafts.json", params: { username: other_user.username }
expect(response.status).to eq(200)
parsed = response.parsed_body
expect(parsed["drafts"].first["title"]).to eq(nil)
describe "#destroy" do
it 'destroys drafts when required' do
user = sign_in(Fabricate(:user))
Draft.set(user, 'xxx', 0, 'hi')
delete "/drafts/xxx.json", params: { sequence: 0 }
expect(response.status).to eq(200)
expect(Draft.get(user, 'xxx', 0)).to eq(nil)
end
end
end