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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
### 2.3.0 (Next)

* [#188](https://github.com/slack-ruby/slack-ruby-bot-server/pull/188): Reduce the database CI matrices from 22 to 12 jobs while retaining representative legacy ORM majors and modern Ruby/Grape 3/4 coverage - [@dblock](https://github.com/dblock), [@Copilot](https://github.com/apps/copilot-swe-agent).
* [#189](https://github.com/slack-ruby/slack-ruby-bot-server/pull/189): Add a prefixed Team fabricator entry point and preserve application-defined `:team` fabricators in the legacy RSpec helper - [@dblock](https://github.com/dblock), [@Copilot](https://github.com/apps/copilot-swe-agent).
* [#186](https://github.com/slack-ruby/slack-ruby-bot-server/pull/186): Document persisted custom Team attributes for both adapters and Rails concern loading/reloading - [@dblock](https://github.com/dblock), [@Copilot](https://github.com/apps/copilot-swe-agent).
* [#183](https://github.com/slack-ruby/slack-ruby-bot-server/pull/183): Add a `config.server_pages` block to configure page middleware options centrally without changing the installed library's defaults - [@dblock](https://github.com/dblock), [@Copilot](https://github.com/apps/copilot-swe-agent).
* [#184](https://github.com/slack-ruby/slack-ruby-bot-server/pull/184): Add a configurable API application and separately mountable team read/registration endpoints, preserving the default API while supporting custom routes and registration-only applications - [@dblock](https://github.com/dblock), [@Copilot](https://github.com/apps/copilot-swe-agent).
Expand Down
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ Build a complete Slack bot service with Slack button integration, in Ruby.
- [HTML Templates](#html-templates)
- [Page Middleware Configuration](#page-middleware-configuration)
- [Access Tokens](#access-tokens)
- [Testing](#testing)
- [Sample Bots Using Slack Ruby Bot Server](#sample-bots-using-slack-ruby-bot-server)
- [Copyright & License](#copyright--license)

Expand Down Expand Up @@ -459,6 +460,28 @@ Without a block, the framework preserves the installed library's defaults and ex

By default the implementation of [Team](lib/slack-ruby-bot-server/models/team) stores the value of the token with all the requested OAuth scopes in both `token` and `activated_user_access_token` (for backwards compatibility), along with `oauth_version` and `oauth_scope`. If a legacy Slack bot integration `bot_access_token` is present, it is stored as `token`, and `activated_user_access_token` is the token that has all the requested OAuth scopes.

## Testing

The optional test helpers use [Fabrication](https://fabricationgem.org/) and Faker. Add `fabrication` and `faker` to your application's test dependencies; neither is a runtime dependency of this gem.

To use the framework's installation defaults without reserving your application's `:team` fabricator name, load the prefixed-only helper:

```ruby
require 'slack-ruby-bot-server/rspec/fabricators'

team = Fabricate(:slack_ruby_bot_server_team)
```

This fabricator creates the existing `::Team` model with unique token/team ID sequences and a generated name. Applications can register their own `:team` before or after this helper, or inherit the framework defaults:

```ruby
Fabricator(:team, from: :slack_ruby_bot_server_team) do
name { 'My application team' }
end
```

The existing `require 'slack-ruby-bot-server/rspec'` remains supported. It loads the prefixed fabricator and registers the legacy `:team` alias only when no `:team` definition already exists. If your application defines `:team` later, replace the legacy require with `slack-ruby-bot-server/rspec/fabricators`; loading both entry points still opts into the legacy alias.

## Sample Bots Using Slack Ruby Bot Server

* [slack-ruby-bot-server-events-sample](https://github.com/slack-ruby/slack-ruby-bot-server-events-sample), a generic sample
Expand Down
16 changes: 16 additions & 0 deletions UPGRADING.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,22 @@ Upgrading Slack-Ruby-Bot-Server

### Upgrading to >= 2.3.0

#### Recommended Test Helper Migration

If your application defines its own `:team` fabricator, replace `require 'slack-ruby-bot-server/rspec'` with `require 'slack-ruby-bot-server/rspec/fabricators'`. This is recommended, not required: the new entry point registers only `:slack_ruby_bot_server_team`, leaving `:team` available regardless of whether your application's fabricator is loaded before or after the helper.

Use `Fabricate(:slack_ruby_bot_server_team)` for the framework defaults, or inherit them in your application's fabricator:

```ruby
require 'slack-ruby-bot-server/rspec/fabricators'

Fabricator(:team, from: :slack_ruby_bot_server_team) do
name { 'My application team' }
end
```

The legacy helper remains supported and registers `:team` only if no definition already exists. Replace the old require rather than adding the new one alongside it; loading both still opts into the legacy alias and can conflict with a `:team` definition loaded later.

#### Status Checks and Inactive Installations

`GET /api/status` now pings only active installations. When Slack returns `account_inactive` or `invalid_auth`, the installation is deactivated through `Service#deactivate!`, and the endpoint returns HTTP `200` with `ping: { "ok": false, "error": "account_inactive" }` (or `"invalid_auth"`). The active-team count reflects that deactivation. Monitoring should inspect the failed `ping` as well as the HTTP status.
Expand Down
4 changes: 1 addition & 3 deletions lib/slack-ruby-bot-server/rspec.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,2 @@
require 'slack-ruby-bot-server'
require 'fabrication'
require 'faker'
require_relative 'rspec/fabricators'
require_relative 'rspec/fabricators/team'
4 changes: 4 additions & 0 deletions lib/slack-ruby-bot-server/rspec/fabricators.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
require 'slack-ruby-bot-server'
require 'fabrication'
require 'faker'
require_relative 'fabricators/slack_ruby_bot_server_team'
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Fabricator(:slack_ruby_bot_server_team, class_name: 'Team') do
token { Fabricate.sequence(:team_token) { |i| "abc-#{i}" } }
team_id { Fabricate.sequence(:team_id) { |i| "T#{i}" } }
name { Faker::Lorem.word }
end
8 changes: 3 additions & 5 deletions lib/slack-ruby-bot-server/rspec/fabricators/team.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
Fabricator(:team) do
token { Fabricate.sequence(:team_token) { |i| "abc-#{i}" } }
team_id { Fabricate.sequence(:team_id) { |i| "T#{i}" } }
name { Faker::Lorem.word }
end
require_relative 'slack_ruby_bot_server_team'

Fabricator(:team, from: :slack_ruby_bot_server_team) unless Fabrication.manager[:team]
77 changes: 77 additions & 0 deletions spec/slack-ruby-bot-server/rspec_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
require 'spec_helper'
require 'open3'
require 'rbconfig'

describe 'RSpec fabricators' do
let(:application_fabricator) do
<<~RUBY
Fabricator(:team, class_name: 'Team') do
name { 'Application team' }
token { 'application-token' }
team_id { 'TAPPLICATION' }
end
RUBY
end

def fabricator_names_after(code)
script = <<~RUBY
require 'logger'
Bundler.require
require 'fabrication'
require 'json'
if defined?(ActiveRecord::Base)
ActiveRecord::Base.establish_connection(ENV.fetch('DATABASE_URL'))
end
#{code}
puts JSON.generate(
application: Fabricate.build(:team).name,
framework: Fabricate.build(:slack_ruby_bot_server_team, name: 'Framework team').name
)
RUBY
output, error, status = Open3.capture3(RbConfig.ruby, '-Ilib', '-rbundler/setup', '-e', script)
expect(status.success?).to be(true), "#{output}\n#{error}"
JSON.parse(output.lines.last)
end

it 'persists framework installations with unique credentials independently of the legacy name' do
first = Fabricate(:slack_ruby_bot_server_team)
second = Fabricate(:slack_ruby_bot_server_team)
expect(Team.find(first.id).token).to eq first.token
expect(first.token).not_to eq second.token
expect(first.team_id).not_to eq second.team_id
end

it 'keeps the legacy helper working without an application fabricator' do
names = fabricator_names_after("require 'slack-ruby-bot-server/rspec'")
expect(names['application']).not_to be_empty
expect(names['framework']).to eq 'Framework team'
end

it 'preserves an application fabricator registered before the legacy helper' do
names = fabricator_names_after(<<~RUBY)
#{application_fabricator}
require 'slack-ruby-bot-server/rspec'
RUBY
expect(names).to eq('application' => 'Application team', 'framework' => 'Framework team')
end

it 'allows applications to inherit and customize framework defaults' do
names = fabricator_names_after(<<~RUBY)
require 'slack-ruby-bot-server/rspec/fabricators'
Fabricator(:team, from: :slack_ruby_bot_server_team) do
name { 'Application team' }
end
RUBY
expect(names).to eq('application' => 'Application team', 'framework' => 'Framework team')
end

%w[before after].each do |order|
it "allows an application fabricator #{order} the prefixed-only helper" do
setup = [application_fabricator, "require 'slack-ruby-bot-server/rspec/fabricators'"]
setup.reverse! if order == 'after'
expect(fabricator_names_after(setup.join("\n"))).to eq(
'application' => 'Application team', 'framework' => 'Framework team'
)
end
end
end
Loading