Skip to content

Commit c4c8ccc

Browse files
Introduce suspenders:accessibility generator
Ported over from #1105 Installs [capybara_accessibility_audit] and [capybara_accessible_selectors]. `./bin/rails g suspenders:accessibility` Introduces `Suspenders::Generators::APIAppUnsupported` module for generators that cannot be run in an [API only][] application. This uses a [concern][] to ensure we raise an error before the generator including the module invokes any of it's methods. [capybara_accessibility_audit]: https://github.com/thoughtbot/capybara_accessibility_audit [capybara_accessible_selectors]: https://github.com/citizensadvice/capybara_accessible_selectors [API only]: https://guides.rubyonrails.org/api_app.html [concern]: https://api.rubyonrails.org/classes/ActiveSupport/Concern.html
1 parent 84e0c95 commit c4c8ccc

File tree

8 files changed

+195
-1
lines changed

8 files changed

+195
-1
lines changed

NEWS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
Unreleased
22

33
* Remove `suspenders` system executable
4+
* Introduce `suspenders:accessibility` generator
5+
* Introduce `Suspenders::Generators::APIAppUnsupported` module and concern
46

57
20230113.0 (January, 13, 2023)
68

README.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,14 @@ end
2121

2222
## Generators
2323

24-
TODO
24+
### Accessibility
25+
26+
Installs [capybara_accessibility_audit] and [capybara_accessible_selectors]
27+
28+
`./bin/rails g suspenders:accessibility`
29+
30+
[capybara_accessibility_audit]: https://github.com/thoughtbot/capybara_accessibility_audit
31+
[capybara_accessible_selectors]: https://github.com/citizensadvice/capybara_accessible_selectors
2532

2633
## Contributing
2734

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
module Suspenders
2+
module Generators
3+
class AccessibilityGenerator < Rails::Generators::Base
4+
include Suspenders::Generators::APIAppUnsupported
5+
6+
desc "Installs capybara_accessibility_audit and capybara_accessible_selectors"
7+
8+
def add_capybara_gems
9+
gem_group :test do
10+
gem "capybara_accessibility_audit"
11+
gem "capybara_accessible_selectors", github: "citizensadvice/capybara_accessible_selectors"
12+
end
13+
Bundler.with_unbundled_env { run "bundle install" }
14+
end
15+
end
16+
end
17+
end

lib/suspenders.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
require "suspenders/version"
22
require "suspenders/railtie"
3+
require "suspenders/generators"
34

45
module Suspenders
56
# Your code goes here...

lib/suspenders/generators.rb

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
require "active_support/concern"
2+
3+
module Suspenders
4+
module Generators
5+
module APIAppUnsupported
6+
class Error < StandardError
7+
def message
8+
"This generator cannot be used on API only applications."
9+
end
10+
end
11+
12+
extend ActiveSupport::Concern
13+
14+
included do
15+
def raise_if_api_only_app
16+
if api_only_app?
17+
raise Suspenders::Generators::APIAppUnsupported::Error
18+
end
19+
end
20+
end
21+
22+
private
23+
24+
def api_only_app?
25+
File.read(Rails.root.join("config/application.rb"))
26+
.match?(/^\s*config\.api_only\s*=\s*true/i)
27+
end
28+
end
29+
end
30+
end
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
require "test_helper"
2+
require "generators/suspenders/accessibility_generator"
3+
4+
module Suspenders
5+
module Generators
6+
class AccessibilityGeneratorTest < Rails::Generators::TestCase
7+
include Suspenders::TestHelpers
8+
9+
tests Suspenders::Generators::AccessibilityGenerator
10+
destination Rails.root
11+
setup :prepare_destination
12+
teardown :restore_destination
13+
14+
test "generator runs without errors" do
15+
assert_nothing_raised do
16+
run_generator
17+
end
18+
end
19+
20+
test "raises if API only application" do
21+
within_api_only_app do
22+
assert_raises Suspenders::Generators::APIAppUnsupported::Error do
23+
run_generator
24+
end
25+
26+
assert_file app_root("Gemfile") do |file|
27+
assert_no_match "capybara_accessibility_audit", file
28+
assert_no_match "capybara_accessible_selectors", file
29+
end
30+
end
31+
end
32+
33+
test "does not raise if API configuration is commented out" do
34+
within_api_only_app do
35+
path = app_root("config/application.rb")
36+
content = File.binread(path).gsub!("config.api_only = true", "# config.api_only = true")
37+
File.binwrite(path, content)
38+
39+
run_generator
40+
41+
assert_file app_root("Gemfile") do |file|
42+
assert_match "capybara_accessibility_audit", file
43+
assert_match "capybara_accessible_selectors", file
44+
end
45+
end
46+
end
47+
48+
test "adds gems to Gemfile" do
49+
expected_output = <<~RUBY
50+
group :test do
51+
gem "capybara_accessibility_audit"
52+
gem "capybara_accessible_selectors", github: "citizensadvice/capybara_accessible_selectors"
53+
end
54+
RUBY
55+
56+
run_generator
57+
58+
assert_file app_root("Gemfile") do |file|
59+
assert_match(expected_output, file)
60+
end
61+
end
62+
63+
test "installs gems with Bundler" do
64+
Bundler.stubs(:with_unbundled_env).yields
65+
generator.expects(:run).with("bundle install").once
66+
67+
capture(:stdout) do
68+
generator.add_capybara_gems
69+
end
70+
end
71+
72+
test "generator has a description" do
73+
description = "Installs capybara_accessibility_audit and capybara_accessible_selectors"
74+
75+
assert_equal description, Suspenders::Generators::AccessibilityGenerator.desc
76+
end
77+
78+
private
79+
80+
def prepare_destination
81+
touch "Gemfile"
82+
end
83+
84+
def restore_destination
85+
remove_file_if_exists "Gemfile"
86+
end
87+
end
88+
end
89+
end

test/suspenders/generators_test.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
require "test_helper"
2+
3+
class Suspenders::GeneratorsTest < ActiveSupport::TestCase
4+
class APIAppUnsupportedTest < Suspenders::GeneratorsTest
5+
test "message returns a custom message" do
6+
expected = "This generator cannot be used on API only applications."
7+
8+
assert_equal expected, Suspenders::Generators::APIAppUnsupported::Error.new.message
9+
end
10+
end
11+
end

test/test_helper.rb

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,41 @@ def touch(file)
4242

4343
FileUtils.touch path
4444
end
45+
46+
def within_api_only_app(&block)
47+
backup_file "config/application.rb"
48+
application_config = <<~RUBY
49+
require_relative "boot"
50+
require "rails/all"
51+
52+
Bundler.require(*Rails.groups)
53+
54+
module Dummy
55+
class Application < Rails::Application
56+
config.load_defaults 7.1
57+
58+
config.autoload_lib(ignore: %w(assets tasks))
59+
60+
config.api_only = true
61+
end
62+
end
63+
RUBY
64+
File.open(app_root("config/application.rb"), "w") { _1.write application_config }
65+
66+
yield
67+
ensure
68+
restore_file "config/application.rb"
69+
end
70+
71+
private
72+
73+
def backup_file(file)
74+
FileUtils.mv app_root(file), app_root("#{file}.bak")
75+
touch file
76+
end
77+
78+
def restore_file(file)
79+
remove_file_if_exists(file)
80+
FileUtils.mv app_root("#{file}.bak"), app_root(file)
81+
end
4582
end

0 commit comments

Comments
 (0)