-
-
Notifications
You must be signed in to change notification settings - Fork 187
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow testing of commands that return multiple messages with respond_with_slack_message #157
Allow testing of commands that return multiple messages with respond_with_slack_message #157
Conversation
a086f41
to
86d3188
Compare
I like the idea. This needs tests and a passing build, please. I would use "once" instead of "at least once" to have a stronger expectation. Maybe something more elaborate can afford for multiple repeated messages. Right now that's not the behavior for a single message. |
I also wonder whether we should instead introduce |
…th_slack_message matcher was failing even if one of the messages received was the correct message. Refactored respond_with_slack_message to allow a check for a single message from multiple responses. Also added respond_with_slack_messages matcher that can take an array of responses to test commands that return multiple messages. Included are rspec tests for both the matchers. README.md has been edited as well to add notes on the new matcher.
86d3188
to
ce559fb
Compare
Refactored to update support for a single message from a group of messages using respond_with_slack_message and added new respond_with_slack_messages to allow checking of multiple responses at once. Agree that it's cleaner that way. Added tests for both matchers and updated README.md with notes on new matcher. A single test case is still failing for me, but it appears to be unrelated to any of my work. The VCR is not matching the response for migration_in_progress and is failing with an error that no response is available in the VCR. |
Build is still failing due to the above mentioned test case. If I'm missing something just let me know, but it doesn't appear that I'm the cause of that failure, copied below.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is good work. Lets deal with the spec failure later. Made some comments. Thanks for hanging in here!
CHANGELOG.md
Outdated
@@ -1,6 +1,7 @@ | |||
### 0.10.5 (Next) | |||
|
|||
* Refactored `SlackRubyBot::MVC::Controller::Base`, consolidated ivar handling, centralized object allocations and DRYed up the code - [@chuckremes](https://github.com/chuckremes). | |||
* [#157](https://github.com/slack-ruby/slack-ruby-bot/pull/157): Added support for checking multiple responses at once via new `respond_with_slack_messages` matcher, and single response out of multiple responses to `response_with_slack_message` matcher - [@gcraig99](https://github.com/gcraig99) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We already had respond_with_slack_message
(typo btw), so I would just say "Added respond_with_slack_messages
RSpec expectation".
You need a period at the end of this for Danger to be happy ;)
README.md
Outdated
@@ -547,6 +547,7 @@ Slack-ruby-bot ships with a number of shared RSpec behaviors that can be used in | |||
|
|||
* [behaves like a slack bot](lib/slack-ruby-bot/rspec/support/slack-ruby-bot/it_behaves_like_a_slack_bot.rb): A bot quacks like a Slack Ruby bot. | |||
* [respond with slack message](lib/slack-ruby-bot/rspec/support/slack-ruby-bot/respond_with_slack_message.rb): The bot responds with a message. | |||
* [respond with slack messages](lib/slack-ruby-bot/rspec/support/slack-ruby-bot/respond_with_slack_messages.rb): The bot responds with a set of message. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
set of messageS or just "multiple messages"
message_command.call(client, Hashie::Mash.new(text: message, channel: channel, user: user)) | ||
expect(client).to have_received(:message).with(channel: channel, text: expected).once |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe this changes behavior, ie. it allows the client to receive multiple messages that aren't the one expected plus the one expected. I think we don't want that, we want expectations to be "precise".
require 'rspec/expectations' | ||
RSpec::Matchers.define :respond_with_slack_messages do |expected| | ||
match do |actual| | ||
raise ArgumentError, 'respond_with_slack_messages expects an array of ordered responses' unless expected.is_a? Array |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would check for Enumerable
instead or maybe just that it responds to each
? This way I can get the messages from some collection, database, whatever, if needed.
expected.each do |exp| | ||
expect(client).to have_received(:message).with(channel: channel, text: exp).once | ||
end | ||
true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above, I think we want exact expectations, making sure only the messages expected have been received. This behavior should have tests in both cases.
def parse(actual) | ||
actual = { message: actual } unless actual.is_a?(Hash) | ||
[actual[:channel] || 'channel', actual[:user] || 'user', actual[:message]] | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's some duplication here with the other expectation. Maybe put the common code in a module and include it?
Without debugging, the VCR error means that something is making an HTTP request that wasn't expecting. You can record that and look at what's being made by changing vcr.rb to record new episodes, but most likely there's a behavior change in the code if it's failing an old spec. |
…changed from start to connect in the slack-ruby-client. Changed vcr file to reflect rtm.connect. Added better logging to respond_with_slack_message and respond_with_slack_messages so it's easier to see why the test is failing. Added a few more tests for the message expectations. Fixed CHANGELOG.md message as requested.
moving common code in expectations to a module and including it. Checking that expected responds to each, instead of testing specifically for an array.
Ok, I think I've addressed all of the concerns and we have a passing build now. If there's anything else just let me know. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Much better. Still seems a bit complicated wrt the implementation, see my comments.
|
||
def client.say(options = {}) | ||
super | ||
@test_received_messages = @test_received_messages.nil? ? '' : @test_received_messages |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sending messages with \n
is going to confuse things, so make this an array:
test_received_messages ||= []
test_received_messages << options
SlackRubyBot::Client.new | ||
end | ||
client = respond_to?(:client) ? send(:client) : SlackRubyBot::Client.new | ||
def client.test_messages |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Try client.attr_accessor :test_messages
instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No go, that causes an error since it's an instance of a class, rather than a class definition.
message_command.call(client, Hashie::Mash.new(text: message, channel: channel, user: user)) | ||
@messages = client.test_messages |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not leave the old code with expect
, and then you don't need the failure_message
at all?
allow(client).to receive(:message) | ||
message_command.call(client, Hashie::Mash.new(text: message, channel: channel, user: user)) | ||
@messages = client.test_messages | ||
expected.each do |exp| |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you make this expect(...)
above you don't need to do this whole saving of @messages
and failure_message
, no? This seems unnecessarily complicated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The expect statements are still there, the issue is that when using the expect statement without the custom failure message and the storage of the received messages, you don't get any useful output.
This is the output without the custom failure message:
-
RSpec it_fails_on_purpose_to_show_output
Failure/Error:
expect(message: "#{SlackRubyBot.config.user} single message")
.to respond_with_slack_message(/failure message/i)expected {:message=>"rubybot single message"} to respond with slack message /failure message/i
-
RSpec respond_with_failure_to_show_output
Failure/Error:
expect(message: "#{SlackRubyBot.config.user} respond 5 times")
.to respond_with_slack_messages(expected_responses)expected {:message=>"rubybot respond 5 times"} to respond with slack messages /response 0/i, /response 1/i, /response 2/i, /response 3/i, /response 4/i, and /response 7/i
This is the output with the custom failure message, much more useful in figuring out why it failed.
-
RSpec it_fails_on_purpose_to_show_output
Failure/Error:
expect(message: "#{SlackRubyBot.config.user} single message")
.to respond_with_slack_message(/failure message/i)`expected to receive message with text: (?i-mx:failure message) once, received:[{:text=>"single response", :channel=>"channel"}]`
-
RSpec respond_with_failure_to_show_output
Failure/Error:
expect(message: "#{SlackRubyBot.config.user} respond 5 times")
.to respond_with_slack_messages(expected_responses)expected to receive messages in order with text: [/response 0/i, /response 1/i, /response 2/i, /response 3/i, /response 4/i, /response 7/i] received:[{:text=>"response 0", :channel=>"channel"}, {:text=>"response 1", :channel=>"channel"}, {:text=>"response 2", :channel=>"channel"}, {:text=>"response 3", :channel=>"channel"}, {:text=>"response 4", :channel=>"channel"}]
df5b7d3
to
887980d
Compare
…pectation failure along side the received message.
Merging, thanks for the good work. |
Allows testing of a single response out of multiple responses, and also allows testing of all responses from a single command call.
Resolves #135