Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
177 changes: 177 additions & 0 deletions spec/integration/status_transitions_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
# frozen_string_literal: true

RSpec.describe "Support-ticket status transitions" do
before { enable_current_plugin }

fab!(:admin)
fab!(:customer) { Fabricate(:user) }
fab!(:category)

def create_ticket(user)
PostCreator.create!(
user,
title: "A support ticket title for the spec",
raw: "Initial ticket body, comfortably long enough.",
category: category.id,
skip_validations: true,
).topic
end

def reply!(user, topic, type: Post.types[:regular])
PostCreator.create!(
user,
topic_id: topic.id,
raw: "A reply body, comfortably long enough.",
post_type: type,
skip_validations: true,
)
end

def set_status!(topic, status, extra = {})
{ status: status }.merge(extra).each { |k, v| topic.custom_fields[k] = v }
topic.save_custom_fields
end

def rows(topic)
CommunityCustomFields::TopicStatusChange.where(topic_id: topic.id).order(:id)
end

describe "topic_created" do
it "seeds status=new for an admin-created topic and records no row" do
topic = create_ticket(admin)

expect(topic.reload.custom_fields["status"]).to eq("new")
expect(rows(topic)).to be_empty
end

it "sets waiting_* when a non-admin creates the topic" do
topic = create_ticket(customer)

expect(topic.reload.custom_fields["status"]).to eq("new")
expect(topic.custom_fields["waiting_id"].to_i).to eq(customer.id)
expect(topic.custom_fields["waiting_since"]).to be_present
end
end

describe "customer reply (non-admin)" do
it "reopens a snoozed topic to open and records a post_creation row" do
topic = create_ticket(admin)
set_status!(topic, "snoozed", assignee_id: customer.id)

post = reply!(customer, topic)

expect(topic.reload.custom_fields["status"]).to eq("open")
expect(rows(topic).last).to have_attributes(
from_status: "snoozed",
to_status: "open",
source: "post_creation",
post_id: post.id,
user_id: nil,
assignee_id: customer.id,
)
end

it "reopens a recently-closed assigned topic to open and reassigns" do
topic = create_ticket(admin)
set_status!(
topic,
"closed",
last_assigned_to_id: customer.id,
closed_at: Time.current.iso8601,
)

reply!(customer, topic)

topic.reload
expect(topic.custom_fields["status"]).to eq("open")
expect(topic.custom_fields["assignee_id"].to_i).to eq(customer.id)
expect(rows(topic).last.to_status).to eq("open")
end

it "reopens a closed topic with no last assignee to new" do
topic = create_ticket(admin)
set_status!(topic, "closed", closed_at: Time.current.iso8601)

reply!(customer, topic)

expect(topic.reload.custom_fields["status"]).to eq("new")
expect(rows(topic).last.to_status).to eq("new")
end

it "reopens a >1-month-closed topic to new despite a last assignee" do
topic = create_ticket(admin)
set_status!(
topic,
"closed",
last_assigned_to_id: customer.id,
closed_at: 2.months.ago.iso8601,
)

reply!(customer, topic)

expect(topic.reload.custom_fields["status"]).to eq("new")
end

it "sets waiting_* and records no row when the status does not change" do
topic = create_ticket(admin)
set_status!(topic, "open")

reply!(customer, topic)

topic.reload
expect(topic.custom_fields["status"]).to eq("open")
expect(topic.custom_fields["waiting_id"].to_i).to eq(customer.id)
expect(rows(topic)).to be_empty
end
end

describe "admin whisper (post_type 4)" do
before { SiteSetting.whispers_allowed_groups = Group::AUTO_GROUPS[:staff].to_s }

it "reopens a snoozed topic to open" do
topic = create_ticket(admin)
set_status!(topic, "snoozed")

reply!(admin, topic, type: Post.types[:whisper])

expect(topic.reload.custom_fields["status"]).to eq("open")
expect(rows(topic).last).to have_attributes(
from_status: "snoozed",
to_status: "open",
source: "post_creation",
)
end

it "reopens a closed assigned topic to open" do
topic = create_ticket(admin)
set_status!(topic, "closed", last_assigned_to_id: customer.id)

reply!(admin, topic, type: Post.types[:whisper])

expect(topic.reload.custom_fields["status"]).to eq("open")
end

it "reopens a closed topic with no last assignee to new" do
topic = create_ticket(admin)
set_status!(topic, "closed")

reply!(admin, topic, type: Post.types[:whisper])

expect(topic.reload.custom_fields["status"]).to eq("new")
end
end

describe "admin regular reply (post_type 1)" do
it "clears waiting_* and records no row" do
topic = create_ticket(admin)
set_status!(topic, "open", waiting_since: 1.hour.ago.iso8601, waiting_id: customer.id)

reply!(admin, topic)

topic.reload
expect(topic.custom_fields["status"]).to eq("open")
expect(topic.custom_fields["waiting_id"]).to be_blank
expect(rows(topic)).to be_empty
end
end
end
117 changes: 117 additions & 0 deletions spec/requests/community_custom_fields/custom_fields_controller_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
# frozen_string_literal: true

RSpec.describe "CommunityCustomFields::CustomFieldsController", type: :request do
before { enable_current_plugin }

fab!(:admin)
fab!(:assignee) { Fabricate(:user) }
fab!(:topic)

STATUSES = %w[new open snoozed closed]

def set_status(topic, status, extra = {})
{ status: status }.merge(extra).each { |k, v| topic.custom_fields[k] = v }
topic.save_custom_fields
end

def put_fields(topic, fields)
put "/admin/plugins/community-custom-fields/#{topic.id}.json", params: { custom_field: fields }
end

def rows(topic)
CommunityCustomFields::TopicStatusChange.where(topic_id: topic.id).order(:id)
end

context "as an admin" do
before { sign_in(admin) }

STATUSES.each do |from|
STATUSES.each do |to|
next if from == to

it "records an api_update row for #{from} -> #{to}" do
set_status(topic, from)
put_fields(topic, status: to)

expect(response.status).to eq(200)
expect(topic.reload.custom_fields["status"]).to eq(to)
expect(rows(topic).count).to eq(1)
expect(rows(topic).last).to have_attributes(
from_status: from,
to_status: to,
source: "api_update",
user_id: admin.id,
post_id: nil,
)
expect(rows(topic).last.duration).to be >= 0
end
end
end

it "records a from_status=null row when the topic had no prior status" do
expect(topic.custom_fields["status"]).to be_nil

put_fields(topic, status: "open")

expect(response.status).to eq(200)
expect(rows(topic).count).to eq(1)
expect(rows(topic).last).to have_attributes(from_status: nil, to_status: "open")
expect(rows(topic).last.duration).to be >= 0
end

it "rejects an invalid status with 422 and records nothing" do
set_status(topic, "open")

put_fields(topic, status: "bogus")

expect(response.status).to eq(422)
expect(topic.reload.custom_fields["status"]).to eq("open")
expect(rows(topic)).to be_empty
end

it "records no row when the status does not change" do
set_status(topic, "open")

put_fields(topic, priority: "high")

expect(response.status).to eq(200)
expect(rows(topic)).to be_empty
end

it "attributes the row to the assignee before the change" do
set_status(topic, "open", assignee_id: assignee.id)

put_fields(topic, status: "closed", assignee_id: "")

expect(response.status).to eq(200)
expect(rows(topic).last).to have_attributes(to_status: "closed", assignee_id: assignee.id)
end

it "measures duration from the previous recorded change" do
freeze_time
set_status(topic, "open")
CommunityCustomFields::TopicStatusChange.create!(
topic_id: topic.id,
from_status: "new",
to_status: "open",
source: "api_update",
duration: 0,
created_at: 1.hour.ago,
)

put_fields(topic, status: "closed")

expect(response.status).to eq(200)
expect(rows(topic).last.duration).to eq(1.hour.to_i)
end
end

it "forbids non-admins and records nothing" do
sign_in(Fabricate(:user))

put_fields(topic, status: "open")

expect(response.status).to eq(403)
expect(rows(topic)).to be_empty
end
end
Loading