From 360773a9d5b891221d747f932f32cc3e09d23331 Mon Sep 17 00:00:00 2001 From: Steve Polito Date: Fri, 1 Dec 2023 05:47:29 -0500 Subject: [PATCH] Introduce 'suspenders:stylelint` generator - Assumes we are using `.css` files based on #1146 - Improve test helper - Configure eslint - Configure prettier - Capture yarn warnings --- .../suspenders/stylelint_generator.rb | 41 ++++++ .../templates/stylelint/eslint.json | 6 + .../templates/stylelint/eslintrc.json | 6 + lib/generators/templates/stylelint/prettierrc | 3 + .../templates/stylelint/stylelintrc.json | 3 + .../suspenders/stylelint_generator_test.rb | 135 ++++++++++++++++++ test/test_helper.rb | 7 +- 7 files changed, 200 insertions(+), 1 deletion(-) create mode 100644 lib/generators/suspenders/stylelint_generator.rb create mode 100644 lib/generators/templates/stylelint/eslint.json create mode 100644 lib/generators/templates/stylelint/eslintrc.json create mode 100644 lib/generators/templates/stylelint/prettierrc create mode 100644 lib/generators/templates/stylelint/stylelintrc.json create mode 100644 test/generators/suspenders/stylelint_generator_test.rb diff --git a/lib/generators/suspenders/stylelint_generator.rb b/lib/generators/suspenders/stylelint_generator.rb new file mode 100644 index 000000000..2f1b5a0bb --- /dev/null +++ b/lib/generators/suspenders/stylelint_generator.rb @@ -0,0 +1,41 @@ +module Suspenders + module Generators + class StylelintGenerator < Rails::Generators::Base + source_root File.expand_path("../../templates/stylelint", __FILE__) + + def install_dependencies + run "yarn add stylelint eslint @thoughtbot/stylelint-config @thoughtbot/eslint-config --dev" + end + + def configure_stylelint + copy_file "stylelintrc.json", ".stylelintrc.json" + end + + def configure_eslint + copy_file "eslintrc.json", ".eslintrc.json" + end + + def configure_prettier + copy_file "prettierrc", ".prettierrc" + end + + # TODO: Consider extracting this into Rails + def update_package_json + content = File.read package_json + json = JSON.parse content + json["scripts"] ||= {} + + json["scripts"]["eslint"] = "npx eslint 'app/javascript/**/*.js'" + json["scripts"]["stylelint"] = "npx stylelint 'app/assets/stylesheets/**/*.css'" + + File.write package_json, JSON.pretty_generate(json) + end + + private + + def package_json + Rails.root.join("package.json") + end + end + end +end diff --git a/lib/generators/templates/stylelint/eslint.json b/lib/generators/templates/stylelint/eslint.json new file mode 100644 index 000000000..118e6598b --- /dev/null +++ b/lib/generators/templates/stylelint/eslint.json @@ -0,0 +1,6 @@ +{ + "extends": [ + "@thoughtbot/eslint-config/base", + "@thoughtbot/eslint-config/prettier" + ] +} diff --git a/lib/generators/templates/stylelint/eslintrc.json b/lib/generators/templates/stylelint/eslintrc.json new file mode 100644 index 000000000..118e6598b --- /dev/null +++ b/lib/generators/templates/stylelint/eslintrc.json @@ -0,0 +1,6 @@ +{ + "extends": [ + "@thoughtbot/eslint-config/base", + "@thoughtbot/eslint-config/prettier" + ] +} diff --git a/lib/generators/templates/stylelint/prettierrc b/lib/generators/templates/stylelint/prettierrc new file mode 100644 index 000000000..544138be4 --- /dev/null +++ b/lib/generators/templates/stylelint/prettierrc @@ -0,0 +1,3 @@ +{ + "singleQuote": true +} diff --git a/lib/generators/templates/stylelint/stylelintrc.json b/lib/generators/templates/stylelint/stylelintrc.json new file mode 100644 index 000000000..3171f405a --- /dev/null +++ b/lib/generators/templates/stylelint/stylelintrc.json @@ -0,0 +1,3 @@ +{ + "extends": "@thoughtbot/stylelint-config" +} diff --git a/test/generators/suspenders/stylelint_generator_test.rb b/test/generators/suspenders/stylelint_generator_test.rb new file mode 100644 index 000000000..da71bdb85 --- /dev/null +++ b/test/generators/suspenders/stylelint_generator_test.rb @@ -0,0 +1,135 @@ +require "test_helper" +require "generators/suspenders/stylelint_generator" + +module Suspenders + module Generators + class StylelintGeneratorTest < Rails::Generators::TestCase + include Suspenders::TestHelpers + + tests Suspenders::Generators::StylelintGenerator + destination Rails.root + setup :prepare_destination + teardown :restore_destination + + test "installs dependencies" do + capture(:stderr) do + output = run_generator + + assert_match(/yarn add stylelint eslint @thoughtbot\/stylelint-config @thoughtbot\/eslint-config --dev/, output) + end + end + + test "configures stylelint" do + expected_content = <<~TEXT + { + "extends": "@thoughtbot/stylelint-config" + } + TEXT + + capture(:stderr) { run_generator } + + assert_file app_root(".stylelintrc.json") do |file| + assert_equal expected_content, file + end + end + + test "configures eslint" do + expected_content = <<~TEXT + { + "extends": [ + "@thoughtbot/eslint-config/base", + "@thoughtbot/eslint-config/prettier" + ] + } + TEXT + + capture(:stderr) { run_generator } + + assert_file app_root(".eslintrc.json") do |file| + assert_equal expected_content, file + end + end + + test "configures prettier" do + expected_content = <<~TEXT + { + "singleQuote": true + } + TEXT + + capture(:stderr) { run_generator } + + assert_file app_root(".prettierrc") do |file| + assert_equal expected_content, file + end + end + + test "updates package.json" do + touch "package.json", content: package_json + + capture(:stderr) { run_generator } + + assert_file "package.json" do |file| + assert_equal expected_package_json, file + end + end + + test "updates package.json if script key does not exist" do + touch "package.json", content: package_json(empty: true) + + capture(:stderr) { run_generator } + + assert_file "package.json" do |file| + assert_equal expected_package_json, file + end + end + + test "description" do + skip + end + + private + + def prepare_destination + touch "Gemfile" + touch "package.json", content: package_json(empty: true) + end + + def restore_destination + remove_file_if_exists "Gemfile" + remove_file_if_exists ".stylelintrc.json" + remove_file_if_exists ".eslintrc.json" + remove_file_if_exists ".prettierrc" + remove_file_if_exists "package.json" + remove_file_if_exists "package.json", root: true + remove_file_if_exists "yarn.lock", root: true + end + + def package_json(empty: false) + if empty + <<~JSON.chomp + { + } + JSON + else + <<~JSON.chomp + { + "scripts": {} + } + JSON + end + end + + def expected_package_json + <<~JSON.chomp + { + "scripts": { + "eslint": "npx eslint 'app/javascript/**/*.js'", + "stylelint": "npx stylelint 'app/assets/stylesheets/**/*.css'" + } + } + JSON + end + end + end +end diff --git a/test/test_helper.rb b/test/test_helper.rb index 4fcaa7ebc..2da56f80e 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -38,10 +38,15 @@ def mkdir(dir) FileUtils.mkdir path end - def touch(file) + def touch(file, **options) + content = options[:content] path = app_root file FileUtils.touch path + + if content + File.write app_root(path), content + end end def within_api_only_app(**options, &block)