From b17387a17669bfc9afce7435653cd8c29c686999 Mon Sep 17 00:00:00 2001 From: Azul Date: Sat, 12 Jul 2014 09:12:48 +0200 Subject: some cleanup of the messages api and cuke feature --- .../controller_extension/json_responses.rb | 29 +++++++++ app/controllers/v1/messages_controller.rb | 4 +- app/models/message.rb | 4 ++ app/models/user.rb | 7 +- config/initializers/add_controller_methods.rb | 1 + features/messages.feature | 74 ++++++++++++++++++++++ features/step_definitions/api_steps.rb | 8 +-- features/step_definitions/messages_steps.rb | 32 ++++++++++ features/support/hooks.rb | 14 ++++ test/factories.rb | 4 ++ 10 files changed, 166 insertions(+), 11 deletions(-) create mode 100644 app/controllers/controller_extension/json_responses.rb create mode 100644 features/messages.feature create mode 100644 features/step_definitions/messages_steps.rb 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/features/messages.feature b/features/messages.feature new file mode 100644 index 0000000..34c0892 --- /dev/null +++ b/features/messages.feature @@ -0,0 +1,74 @@ +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 the response status should be "200" + And the response should be: + """ + { "success": "marked as read", + "message": "The message has been marked as read" } + """ + And that message should be marked as read + + 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 be: + """ + { "error": "not found", + "message": "The message could not be found" } + """ + + 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 -- cgit v1.2.3 From 150c80bfc7c469b23f7ac1bac0e42014ad417df6 Mon Sep 17 00:00:00 2001 From: Azul Date: Mon, 14 Jul 2014 17:26:28 +0200 Subject: add translation and fix tests --- config/locales/errors.en.yml | 1 + config/locales/messages.en.yml | 4 ++++ test/functional/v1/messages_controller_test.rb | 4 ++-- test/support/assert_responses.rb | 19 +++++++++++++++++-- 4 files changed, 24 insertions(+), 4 deletions(-) create mode 100644 config/locales/messages.en.yml 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/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 -- cgit v1.2.3 From 20352249fa5dafe3abb2d4b751b1e5c8c0a59abc Mon Sep 17 00:00:00 2001 From: Azul Date: Thu, 17 Jul 2014 19:50:01 +0200 Subject: fix messages feature to match latest response format --- features/messages.feature | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/features/messages.feature b/features/messages.feature index 34c0892..69c5637 100644 --- a/features/messages.feature +++ b/features/messages.feature @@ -44,22 +44,16 @@ Feature: Receive messages for the user Given there is a message for me with: | id | 1a2b3c4d | When I send a PUT request to "/1/messages/1a2b3c4d.json" - Then the response status should be "200" - And the response should be: - """ - { "success": "marked as read", - "message": "The message has been marked as read" } - """ - And that message should be marked as read + 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 be: - """ - { "error": "not found", - "message": "The message could not be found" } - """ + 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 @@ -70,5 +64,3 @@ Feature: Receive messages for the user """ [] """ - - -- cgit v1.2.3