summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorazul <azul@leap.se>2014-07-18 12:21:49 +0200
committerazul <azul@leap.se>2014-07-18 12:21:49 +0200
commitbbd41c9bfd2cb88a88d7436dd58a8b46a5d10cf1 (patch)
tree00b39da219151473437c02ce35344117bcd5b2fa
parentade74d8a9091ae607586d7b287a0579a2ee7af8e (diff)
parent20352249fa5dafe3abb2d4b751b1e5c8c0a59abc (diff)
Merge pull request #180 from azul/feature/messages-api
Feature/messages api
-rw-r--r--app/controllers/controller_extension/json_responses.rb29
-rw-r--r--app/controllers/v1/messages_controller.rb4
-rw-r--r--app/models/message.rb4
-rw-r--r--app/models/user.rb7
-rw-r--r--config/initializers/add_controller_methods.rb1
-rw-r--r--config/locales/errors.en.yml1
-rw-r--r--config/locales/messages.en.yml4
-rw-r--r--features/messages.feature66
-rw-r--r--features/step_definitions/api_steps.rb8
-rw-r--r--features/step_definitions/messages_steps.rb32
-rw-r--r--features/support/hooks.rb14
-rw-r--r--test/factories.rb4
-rw-r--r--test/functional/v1/messages_controller_test.rb4
-rw-r--r--test/support/assert_responses.rb19
14 files changed, 182 insertions, 15 deletions
diff --git a/app/controllers/controller_extension/json_responses.rb b/app/controllers/controller_extension/json_responses.rb
new file mode 100644
index 0000000..da1ae58
--- /dev/null
+++ b/app/controllers/controller_extension/json_responses.rb
@@ -0,0 +1,29 @@
+module ControllerExtension::JsonResponses
+ extend ActiveSupport::Concern
+
+ private
+
+ def success(key)
+ json_message :success, key
+ end
+
+ def error(key)
+ json_message :error, key
+ end
+
+ def json_message(type, key)
+ long_key = "#{controller_string}.#{action_string}.#{key}"
+ { type => key.to_s,
+ :message => I18n.t(long_key, cascade: true) }
+ end
+
+ def controller_string
+ self.class.name.underscore.
+ sub(/_controller$/, '').
+ sub(/^v\d\//, '')
+ end
+
+ def action_string
+ params[:action]
+ end
+end
diff --git a/app/controllers/v1/messages_controller.rb b/app/controllers/v1/messages_controller.rb
index a9b93a9..a496378 100644
--- a/app/controllers/v1/messages_controller.rb
+++ b/app/controllers/v1/messages_controller.rb
@@ -11,9 +11,9 @@ module V1
if message = Message.find(params[:id])
message.mark_as_read_by(current_user)
message.save
- render json: true
+ render json: success(:marked_as_read)
else
- render json: false
+ render json: error(:not_found), status: :not_found
end
end
diff --git a/app/models/message.rb b/app/models/message.rb
index 424f094..2478f3f 100644
--- a/app/models/message.rb
+++ b/app/models/message.rb
@@ -26,4 +26,8 @@ class Message < CouchRest::Model::Base
def unread_by?(user)
user_ids_to_show.include?(user.id)
end
+
+ def as_json(*args, &block)
+ {"id" => id, "text" => text}.as_json(*args, &block)
+ end
end
diff --git a/app/models/user.rb b/app/models/user.rb
index 6bc5841..9ac7d3d 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -92,12 +92,9 @@ class User < CouchRest::Model::Base
Ticket.for_user(self).limit(count).all #defaults to having most recent updated first
end
- def messages(unseen = true)
+ def messages
#TODO for now this only shows unseen messages. Will we ever want seen ones? Is it necessary to store?
-
- # we don't want to emit all the userids associated with a message, so only emit id and text.
- Message.by_user_ids_to_show.key(self.id).map { |message| [message.id, message.text] }
-
+ Message.by_user_ids_to_show.key(self.id)
end
# DEPRECATED
diff --git a/config/initializers/add_controller_methods.rb b/config/initializers/add_controller_methods.rb
index f107544..4ad4213 100644
--- a/config/initializers/add_controller_methods.rb
+++ b/config/initializers/add_controller_methods.rb
@@ -2,5 +2,6 @@ ActiveSupport.on_load(:application_controller) do
include ControllerExtension::Authentication
include ControllerExtension::TokenAuthentication
include ControllerExtension::Flash
+ include ControllerExtension::JsonResponses
include ControllerExtension::Errors
end
diff --git a/config/locales/errors.en.yml b/config/locales/errors.en.yml
index 93feab1..e0a909f 100644
--- a/config/locales/errors.en.yml
+++ b/config/locales/errors.en.yml
@@ -9,3 +9,4 @@ en:
text:
not_found: "You may have mistyped the address or the page may have moved."
server_error: The problem has been logged and we will look into it.
+ not_found: Not found.
diff --git a/config/locales/messages.en.yml b/config/locales/messages.en.yml
new file mode 100644
index 0000000..d9d7613
--- /dev/null
+++ b/config/locales/messages.en.yml
@@ -0,0 +1,4 @@
+en:
+ messages:
+ not_found: That message could not be found.
+ marked_as_read: Message has been marked as read.
diff --git a/features/messages.feature b/features/messages.feature
new file mode 100644
index 0000000..69c5637
--- /dev/null
+++ b/features/messages.feature
@@ -0,0 +1,66 @@
+Feature: Receive messages for the user
+
+ In order to stay in touch with the provider
+ As an authenticated user
+ I want to receive messages from the provider
+
+ Background:
+ Given I authenticated
+ Given I set headers:
+ | Accept | application/json |
+ | Content-Type | application/json |
+ | Authorization | Token token="MY_AUTH_TOKEN" |
+
+ Scenario: There are no messages yet
+ When I send a GET request to "/1/messages.json"
+ Then the response status should be "200"
+ And the response should be:
+ """
+ []
+ """
+
+ Scenario: Fetch the unread messages
+ Given there is a message for me with:
+ | id | 1a2b3c4d |
+ | text | Your provider says hi ! |
+ When I send a GET request to "/1/messages.json"
+ Then the response status should be "200"
+ And the response should be:
+ """
+ [{
+ "id": "1a2b3c4d",
+ "text": "Your provider says hi !"
+ }]
+ """
+
+ Scenario: Send unread messages until marked as read
+ Given there is a message for me
+ And I have sent a GET request to "/1/messages.json"
+ When I send a GET request to "/1/messages.json"
+ Then the response status should be "200"
+ And the response should include that message
+
+ Scenario: Mark message as read
+ Given there is a message for me with:
+ | id | 1a2b3c4d |
+ When I send a PUT request to "/1/messages/1a2b3c4d.json"
+ Then that message should be marked as read
+ And the response status should be "200"
+ And the response should have "success" with "marked_as_read"
+ And the response should have "message"
+
+ Scenario: Message not found
+ When I send a PUT request to "/1/messages/1a2b3c4d.json"
+ Then the response status should be "404"
+ And the response should have "error" with "not_found"
+ And the response should have "message"
+
+ Scenario: Do not send read messages
+ Given there is a message for me
+ And that message is marked as read
+ When I send a GET request to "/1/messages.json"
+ Then the response status should be "200"
+ And the response should be:
+ """
+ []
+ """
diff --git a/features/step_definitions/api_steps.rb b/features/step_definitions/api_steps.rb
index a4f369c..7188694 100644
--- a/features/step_definitions/api_steps.rb
+++ b/features/step_definitions/api_steps.rb
@@ -13,8 +13,9 @@ end
Given /^I set headers:$/ do |headers|
headers.rows_hash.each do |key,value|
- value.sub!('MY_AUTH_TOKEN', @my_auth_token.to_s) if @my_auth_token
- header key, value
+ replace = value.dup
+ replace.sub!('MY_AUTH_TOKEN', @my_auth_token.to_s) if @my_auth_token
+ header key, replace
end
end
@@ -36,7 +37,7 @@ When /^I digest\-authenticate as the user "(.*?)" with the password "(.*?)"$/ do
digest_authorize user, pass
end
-When /^I send a (GET|POST|PUT|DELETE) request (?:for|to) "([^"]*)"(?: with the following:)?$/ do |*args|
+When /^I (?:have sent|send) a (GET|POST|PUT|DELETE) request (?:for|to) "([^"]*)"(?: with the following:)?$/ do |*args|
request_type = args.shift
path = args.shift
input = args.shift
@@ -50,7 +51,6 @@ When /^I send a (GET|POST|PUT|DELETE) request (?:for|to) "([^"]*)"(?: with the f
request_opts[:input] = input
end
end
-
request path, request_opts
end
diff --git a/features/step_definitions/messages_steps.rb b/features/step_definitions/messages_steps.rb
new file mode 100644
index 0000000..30bc7c3
--- /dev/null
+++ b/features/step_definitions/messages_steps.rb
@@ -0,0 +1,32 @@
+Given /^there is a message for me$/ do
+ @message = FactoryGirl.create :message, user_ids_to_show: [@user.id]
+end
+
+Given /^there is a message for me with:$/ do |options|
+ attributes = options.rows_hash
+ attributes.merge! user_ids_to_show: [@user.id]
+ if old_message = Message.find(attributes['id'])
+ old_message.destroy
+ end
+ @message = FactoryGirl.create :message, attributes
+end
+
+Given(/^that message is marked as read$/) do
+ @message.mark_as_read_by(@user)
+ @message.save
+end
+
+Then /^the response should (not)?\s?include that message$/ do |negative|
+ json = JSON.parse(last_response.body)
+ message = json.detect{|message| message['id'] == @message.id}
+ if negative.present?
+ assert !message
+ else
+ assert_equal @message.text, message['text']
+ end
+end
+
+Then /^that message should be marked as read$/ do
+ assert @message.reload.read_by? @user
+ assert !@message.unread_by?(@user)
+end
diff --git a/features/support/hooks.rb b/features/support/hooks.rb
index 19928d8..f11e602 100644
--- a/features/support/hooks.rb
+++ b/features/support/hooks.rb
@@ -5,6 +5,7 @@ After '@tempfile' do
end
end
+# store end of server log for failing scenarios
After do |scenario|
if scenario.failed?
logfile_path = Rails.root + 'tmp'
@@ -16,3 +17,16 @@ After do |scenario|
end
end
end
+
+# clear all records we created
+After do
+ names = self.instance_variables.reject do |v|
+ v.to_s.starts_with?('@_')
+ end
+ names.each do |name|
+ record = self.instance_variable_get name
+ if record.is_a?(CouchRest::Model::Base) && record.persisted?
+ record.reload && record.destroy
+ end
+ end
+end
diff --git a/test/factories.rb b/test/factories.rb
index a96d48c..e16c738 100644
--- a/test/factories.rb
+++ b/test/factories.rb
@@ -47,4 +47,8 @@ FactoryGirl.define do
-----END PGP PUBLIC KEY BLOCK-----
EOPGP
end
+
+ factory :message do
+ text Faker::Lorem.paragraph
+ end
end
diff --git a/test/functional/v1/messages_controller_test.rb b/test/functional/v1/messages_controller_test.rb
index a50fded..6f7ea5d 100644
--- a/test/functional/v1/messages_controller_test.rb
+++ b/test/functional/v1/messages_controller_test.rb
@@ -30,7 +30,7 @@ class V1::MessagesControllerTest < ActionController::TestCase
@message.reload
assert !@message.user_ids_to_show.include?(@user.id)
assert @message.user_ids_have_shown.include?(@user.id)
- assert_json_response true
+ assert_success :marked_as_read
end
test "do not get seen messages" do
@@ -46,7 +46,7 @@ class V1::MessagesControllerTest < ActionController::TestCase
test "mark read responds even with bad inputs" do
login @user
put :update, :id => 'more nonsense'
- assert_json_response false
+ assert_not_found
end
test "fails if not authenticated" do
diff --git a/test/support/assert_responses.rb b/test/support/assert_responses.rb
index 1c9d49d..7724fb4 100644
--- a/test/support/assert_responses.rb
+++ b/test/support/assert_responses.rb
@@ -20,6 +20,22 @@ module AssertResponses
response
end
+ def response_content
+ json_response || get_response.body
+ end
+
+ def assert_success(message)
+ assert_response :success
+ assert_response_includes :success
+ assert_equal message.to_s, json_response[:success] if message.present?
+ end
+
+ def assert_not_found
+ assert_response :not_found
+ assert_response_includes :error
+ assert_equal 'not_found', json_response[:error]
+ end
+
def assert_text_response(body = nil)
assert_equal 'text/plain', content_type
unless body.nil?
@@ -45,8 +61,7 @@ module AssertResponses
# checks for the presence of a key in a json response
# or a string in a text response
def assert_response_includes(string_or_key)
- response = json_response || get_response.body
- assert response.include?(string_or_key),
+ assert response_content.include?(string_or_key),
"response should have included #{string_or_key}"
end