From 2fec28a3a3ba9adbae0dbdabe3785aa1aabb0ca6 Mon Sep 17 00:00:00 2001 From: Andrea Fomera Date: Mon, 29 Sep 2025 18:20:09 -0600 Subject: [PATCH 1/5] Start of shaping up the Hanami CLI with some colorized output --- lib/hanami/cli/commands/gem/new.rb | 33 +++++-- lib/hanami/cli/files.rb | 13 ++- lib/hanami/cli/formatter.rb | 151 +++++++++++++++++++++++++++++ 3 files changed, 183 insertions(+), 14 deletions(-) create mode 100644 lib/hanami/cli/formatter.rb diff --git a/lib/hanami/cli/commands/gem/new.rb b/lib/hanami/cli/commands/gem/new.rb index 0562cada..9f88f08a 100644 --- a/lib/hanami/cli/commands/gem/new.rb +++ b/lib/hanami/cli/commands/gem/new.rb @@ -2,6 +2,7 @@ require "dry/inflector" require_relative "../../errors" +require_relative "../../formatter" module Hanami module CLI @@ -157,31 +158,43 @@ def call( skip_view: skip_view, database: normalized_database ) + out.puts Formatter.header("Setting up #{app}...") + generator.call(app, context: context) do if skip_install - out.puts "Skipping installation, please enter `#{app}' directory and run `bundle exec hanami install'" + out.puts "" + out.puts Formatter.info("Skipping installation") + out.puts Formatter.dim(" To complete setup, run: cd #{app} && bundle exec hanami install") else - out.puts "Running bundle install..." + out.puts "" + out.puts Formatter.info("Installing dependencies...") bundler.install! unless skip_assets - out.puts "Running npm install..." + out.puts Formatter.info("Installing npm packages...") system_call.call("npm", ["install"]).tap do |result| unless result.successful? - puts "NPM ERROR:" - puts(result.err.lines.map { |line| line.prepend(" ") }) + out.puts Formatter.error("NPM installation failed:") + out.puts(result.err.lines.map { |line| Formatter.dim(" #{line}") }) end end end - out.puts "Running hanami install..." + out.puts Formatter.info("Running hanami install...") run_install_command!(head: head) - out.puts "Running bundle binstubs hanami-cli rake..." + out.puts Formatter.info("Running bundle binstubs hanami-cli rake...") install_binstubs! - out.puts "Initializing git repository..." + out.puts Formatter.info("Initializing git repository...") init_git_repository + + out.puts "" + out.puts Formatter.success("Successfully created #{app}!") + out.puts "" + out.puts Formatter.dim("Next steps:") + out.puts Formatter.dim(" cd #{app}") + out.puts Formatter.dim(" bundle exec hanami server") end end end @@ -227,8 +240,8 @@ def install_binstubs! def init_git_repository system_call.call("git", ["init"]).tap do |result| unless result.successful? - out.puts "WARNING: Failed to initialize git repository" - out.puts(result.err.lines.map { |line| line.prepend(" ") }) + out.puts Formatter.warning("Failed to initialize git repository") + out.puts(result.err.lines.map { |line| Formatter.dim(" #{line}") }) end end end diff --git a/lib/hanami/cli/files.rb b/lib/hanami/cli/files.rb index e8b30118..c842d4c0 100644 --- a/lib/hanami/cli/files.rb +++ b/lib/hanami/cli/files.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true require "dry/files" +require_relative "formatter" module Hanami module CLI @@ -43,7 +44,7 @@ def mkdir(path) return if exist?(path) super - created(dir_path(path)) + created_directory(dir_path(path)) end # @since 2.0.0 @@ -83,15 +84,19 @@ def delete_keepfiles(path) end def updated(path) - out.puts "Updated #{path}" + out.puts Formatter.updated(path) end def created(path) - out.puts "Created #{path}" + out.puts Formatter.created(path) + end + + def created_directory(path) + out.puts Formatter.created_directory(path) end def within_folder(path) - out.puts "-> Within #{dir_path(path)}" + out.puts Formatter.dim("-> Entering `#{path}/` directory...") end def dir_path(path) diff --git a/lib/hanami/cli/formatter.rb b/lib/hanami/cli/formatter.rb new file mode 100644 index 00000000..1eebfc40 --- /dev/null +++ b/lib/hanami/cli/formatter.rb @@ -0,0 +1,151 @@ +# frozen_string_literal: true + +module Hanami + module CLI + # Provides formatting utilities for CLI output including colors and icons + # + # @api private + # @since 2.3.0 + module Formatter + # ANSI color codes + COLORS = { + reset: "\e[0m", + bold: "\e[1m", + green: "\e[32m", + blue: "\e[34m", + cyan: "\e[36m", + yellow: "\e[33m", + red: "\e[31m", + gray: "\e[90m" + }.freeze + + # Icons for different operations + ICONS = { + create: "✓", + update: "↻", + info: "→", + warning: "⚠", + error: "✗", + success: "✓" + }.freeze + + module_function + + # Wraps text in color codes + # + # @param text [String] the text to colorize + # @param color [Symbol] the color name from COLORS + # @return [String] colorized text + # + # @api private + def colorize(text, color) + return text unless $stdout.tty? + + "#{COLORS[color]}#{text}#{COLORS[:reset]}" + end + + # Formats a create message + # + # @param path [String] the path that was created + # @return [String] formatted message + # + # @api private + def created(path) + icon = colorize(ICONS[:create], :green) + label = colorize("create", :green) + " #{icon} #{label} #{path}" + end + + # Formats a create directory message + # + # @param path [String] the directory path that was created + # @return [String] formatted message + # + # @api private + def created_directory(path) + icon = colorize(ICONS[:create], :green) + label = colorize("create directory", :green) + "#{icon} #{label} #{path}" + end + + # Formats an update message + # + # @param path [String] the path that was updated + # @return [String] formatted message + # + # @api private + def updated(path) + icon = colorize(ICONS[:update], :cyan) + label = colorize("update", :cyan) + " #{icon} #{label} #{path}" + end + + # Formats an info message + # + # @param text [String] the message text + # @return [String] formatted message + # + # @api private + def info(text) + icon = colorize(ICONS[:info], :blue) + "#{icon} #{text}" + end + + # Formats a success message + # + # @param text [String] the message text + # @return [String] formatted message + # + # @api private + def success(text) + icon = colorize(ICONS[:success], :green) + label = colorize("✓", :green) + "#{label} #{colorize(text, :green)}" + end + + # Formats a warning message + # + # @param text [String] the message text + # @return [String] formatted message + # + # @api private + def warning(text) + icon = colorize(ICONS[:warning], :yellow) + label = colorize("warning", :yellow) + "#{icon} #{label} #{text}" + end + + # Formats an error message + # + # @param text [String] the message text + # @return [String] formatted message + # + # @api private + def error(text) + icon = colorize(ICONS[:error], :red) + label = colorize("error", :red) + "#{icon} #{label} #{text}" + end + + # Formats a section header + # + # @param text [String] the header text + # @return [String] formatted header + # + # @api private + def header(text) + "\n#{colorize(text, :bold)}" + end + + # Formats a dim/secondary text + # + # @param text [String] the text to dim + # @return [String] formatted text + # + # @api private + def dim(text) + text # No special dim color, just return plain text for now + end + end + end +end From 2528a66ef0459132a4c52943f0f698d4238d2c3e Mon Sep 17 00:00:00 2001 From: Andrea Fomera Date: Mon, 29 Sep 2025 21:02:46 -0600 Subject: [PATCH 2/5] Swap to use dev command vs server so all servers boot --- lib/hanami/cli/commands/gem/new.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/hanami/cli/commands/gem/new.rb b/lib/hanami/cli/commands/gem/new.rb index 9f88f08a..04b1c910 100644 --- a/lib/hanami/cli/commands/gem/new.rb +++ b/lib/hanami/cli/commands/gem/new.rb @@ -194,7 +194,7 @@ def call( out.puts "" out.puts Formatter.dim("Next steps:") out.puts Formatter.dim(" cd #{app}") - out.puts Formatter.dim(" bundle exec hanami server") + out.puts Formatter.dim(" bundle exec hanami dev") end end end From 497f6b563ed9a798ca8272c644f2607da65b05dd Mon Sep 17 00:00:00 2001 From: Andrea Fomera Date: Thu, 23 Oct 2025 20:55:33 -0600 Subject: [PATCH 3/5] Add comment and spec for Formatter class --- lib/hanami/cli/formatter.rb | 2 + spec/unit/hanami/cli/commands/gem/new_spec.rb | 136 +++--- spec/unit/hanami/cli/formatter_spec.rb | 427 ++++++++++++++++++ 3 files changed, 497 insertions(+), 68 deletions(-) create mode 100644 spec/unit/hanami/cli/formatter_spec.rb diff --git a/lib/hanami/cli/formatter.rb b/lib/hanami/cli/formatter.rb index 1eebfc40..15e75d9b 100644 --- a/lib/hanami/cli/formatter.rb +++ b/lib/hanami/cli/formatter.rb @@ -4,6 +4,8 @@ module Hanami module CLI # Provides formatting utilities for CLI output including colors and icons # + # There is significant overlap with Hanami-Utils ShellColor module, but hasn't been merged together yet. + # # @api private # @since 2.3.0 module Formatter diff --git a/spec/unit/hanami/cli/commands/gem/new_spec.rb b/spec/unit/hanami/cli/commands/gem/new_spec.rb index 787341a3..ccd8cd1e 100644 --- a/spec/unit/hanami/cli/commands/gem/new_spec.rb +++ b/spec/unit/hanami/cli/commands/gem/new_spec.rb @@ -102,11 +102,11 @@ subject.call(app: app, **kwargs) expect(fs.directory?(app)).to be(true) - expect(output).to include("Created #{app}/") - expect(output).to include("-> Within #{app}/") - expect(output).to include("Running bundle install...") - expect(output).to include("Running npm install...") - expect(output).to include("Running hanami install...") + expect(output).to include(Hanami::CLI::Formatter.created_directory("#{app}/")) + expect(output).to include("-> Entering `#{app}/` directory...") + expect(output).to include(Hanami::CLI::Formatter.info("Installing dependencies...")) + expect(output).to include(Hanami::CLI::Formatter.info("Installing npm packages...")) + expect(output).to include(Hanami::CLI::Formatter.info("Running hanami install...")) fs.chdir(app) do # .gitignore @@ -120,7 +120,7 @@ db/*.sqlite EXPECTED expect(fs.read(".gitignore")).to eq(gitignore) - expect(output).to include("Created .gitignore") + expect(output).to include(Hanami::CLI::Formatter.created(".gitignore")) # .env env = <<~EXPECTED @@ -128,7 +128,7 @@ DATABASE_URL=sqlite://db/#{app}.sqlite EXPECTED expect(fs.read(".env")).to eq(env) - expect(output).to include("Created .env") + expect(output).to include(Hanami::CLI::Formatter.created(".env")) # README.md readme = <<~EXPECTED @@ -149,7 +149,7 @@ - [Hanami API Doc](https://gemdocs.org/gems/hanami/latest) EXPECTED expect(fs.read("README.md")).to eq(readme) - expect(output).to include("Created README.md") + expect(output).to include(Hanami::CLI::Formatter.created("README.md")) # Gemfile hanami_version = Hanami::CLI::Generators::Version.gem_requirement @@ -189,7 +189,7 @@ end EXPECTED expect(fs.read("Gemfile")).to eq(gemfile) - expect(output).to include("Created Gemfile") + expect(output).to include(Hanami::CLI::Formatter.created("Gemfile")) # package.json hanami_npm_version = Hanami::CLI::Generators::Version.npm_package_requirement @@ -204,7 +204,7 @@ } EXPECTED expect(fs.read("package.json")).to eq(package_json) - expect(output).to include("Created package.json") + expect(output).to include(Hanami::CLI::Formatter.created("package.json")) # Procfile.dev procfile = <<~EXPECTED @@ -212,7 +212,7 @@ assets: bundle exec hanami assets watch EXPECTED expect(fs.read("Procfile.dev")).to eq(procfile) - expect(output).to include("Created Procfile.dev") + expect(output).to include(Hanami::CLI::Formatter.created("Procfile.dev")) # Rakefile rakefile = <<~EXPECTED @@ -224,7 +224,7 @@ Rake.add_rakelib "lib/tasks" EXPECTED expect(fs.read("Rakefile")).to eq(rakefile) - expect(output).to include("Created Rakefile") + expect(output).to include(Hanami::CLI::Formatter.created("Rakefile")) # config.ru config_ru = <<~EXPECTED @@ -235,7 +235,7 @@ run Hanami.app EXPECTED expect(fs.read("config.ru")).to eq(config_ru) - expect(output).to include("Created config.ru") + expect(output).to include(Hanami::CLI::Formatter.created("config.ru")) # bin/dev bin_dev = <<~EXPECTED @@ -250,7 +250,7 @@ EXPECTED expect(fs.read("bin/dev")).to eq(bin_dev) expect(fs.executable?("bin/dev")).to be(true) - expect(output).to include("Created bin/dev") + expect(output).to include(Hanami::CLI::Formatter.created("bin/dev")) # config/app.rb hanami_app = <<~EXPECTED @@ -264,7 +264,7 @@ class App < Hanami::App end EXPECTED expect(fs.read("config/app.rb")).to eq(hanami_app) - expect(output).to include("Created config/app.rb") + expect(output).to include(Hanami::CLI::Formatter.created("config/app.rb")) # config/assets.js assets = <<~EXPECTED @@ -287,7 +287,7 @@ class App < Hanami::App }); EXPECTED expect(fs.read("config/assets.js")).to eq(assets) - expect(output).to include("Created config/assets.js") + expect(output).to include(Hanami::CLI::Formatter.created("config/assets.js")) # config/settings.rb settings = <<~EXPECTED @@ -302,7 +302,7 @@ class Settings < Hanami::Settings end EXPECTED expect(fs.read("config/settings.rb")).to eq(settings) - expect(output).to include("Created config/settings.rb") + expect(output).to include(Hanami::CLI::Formatter.created("config/settings.rb")) # config/routes.rb routes = <<~EXPECTED @@ -315,7 +315,7 @@ class Routes < Hanami::Routes end EXPECTED expect(fs.read("config/routes.rb")).to eq(routes) - expect(output).to include("Created config/routes.rb") + expect(output).to include(Hanami::CLI::Formatter.created("config/routes.rb")) # config/puma.rb puma = <<~EXPECTED @@ -368,13 +368,13 @@ class Routes < Hanami::Routes end EXPECTED expect(fs.read("config/puma.rb")).to eq(puma) - expect(output).to include("Created config/puma.rb") + expect(output).to include(Hanami::CLI::Formatter.created("config/puma.rb")) # lib/tasks/.keep tasks_keep = <<~EXPECTED EXPECTED expect(fs.read("lib/tasks/.keep")).to eq(tasks_keep) - expect(output).to include("Created lib/tasks/.keep") + expect(output).to include(Hanami::CLI::Formatter.created("lib/tasks/.keep")) # app/action.rb action = <<~EXPECTED @@ -392,7 +392,7 @@ class Action < Hanami::Action end EXPECTED expect(fs.read("app/action.rb")).to eq(action) - expect(output).to include("Created app/action.rb") + expect(output).to include(Hanami::CLI::Formatter.created("app/action.rb")) # app/view.rb view = <<~RUBY @@ -407,7 +407,7 @@ class View < Hanami::View end RUBY expect(fs.read("app/view.rb")).to eq(view) - expect(output).to include("Created app/view.rb") + expect(output).to include(Hanami::CLI::Formatter.created("app/view.rb")) # app/views/helpers.rb helpers = <<~RUBY @@ -423,7 +423,7 @@ module Helpers end RUBY expect(fs.read("app/views/helpers.rb")).to eq(helpers) - expect(output).to include("Created app/views/helpers.rb") + expect(output).to include(Hanami::CLI::Formatter.created("app/views/helpers.rb")) # app/templates/layouts/app.html.erb layout = <<~ERB @@ -443,14 +443,14 @@ module Helpers ERB expect(fs.read("app/templates/layouts/app.html.erb")).to eq(layout) - expect(output).to include("Created app/templates/layouts/app.html.erb") + expect(output).to include(Hanami::CLI::Formatter.created("app/templates/layouts/app.html.erb")) # app/assets/js/app.js app_js = <<~EXPECTED import "../css/app.css"; EXPECTED expect(fs.read("app/assets/js/app.js")).to eq(app_js) - expect(output).to include("Created app/assets/js/app.js") + expect(output).to include(Hanami::CLI::Formatter.created("app/assets/js/app.js")) # app/assets/css/app.css app_css = <<~EXPECTED @@ -461,7 +461,7 @@ module Helpers } EXPECTED expect(fs.read("app/assets/css/app.css")).to eq(app_css) - expect(output).to include("Created app/assets/css/app.css") + expect(output).to include(Hanami::CLI::Formatter.created("app/assets/css/app.css")) # app/assets/images/favicon.ico expect(fs.exist?("app/assets/images/favicon.ico")).to be(true) @@ -481,7 +481,7 @@ module Types end EXPECTED expect(fs.read("lib/#{app}/types.rb")).to eq(types) - expect(output).to include("Created lib/bookshelf/types.rb") + expect(output).to include(Hanami::CLI::Formatter.created("lib/bookshelf/types.rb")) # app/operation.rb action = <<~EXPECTED @@ -496,7 +496,7 @@ class Operation < Dry::Operation end EXPECTED expect(fs.read("app/operation.rb")).to eq(action) - expect(output).to include("Created app/operation.rb") + expect(output).to include(Hanami::CLI::Formatter.created("app/operation.rb")) # public/ error pages expect(fs.read("public/404.html")).to include %(The page you were looking for doesn’t exist (404)) @@ -563,7 +563,7 @@ class Operation < Dry::Operation end EXPECTED expect(fs.read("Gemfile")).to eq(gemfile) - expect(output).to include("Created Gemfile") + expect(output).to include(Hanami::CLI::Formatter.created("Gemfile")) end end end @@ -587,11 +587,11 @@ class Operation < Dry::Operation subject.call(app: app, **kwargs) expect(fs.directory?(app)).to be(true) - expect(output).to include("Created #{app}/") - expect(output).to include("-> Within #{app}/") - expect(output).to include("Running bundle install...") - expect(output).to include("Running npm install...") - expect(output).to include("Running hanami install...") + expect(output).to include(Hanami::CLI::Formatter.created_directory("#{app}/")) + expect(output).to include("-> Entering `#{app}/` directory...") + expect(output).to include(Hanami::CLI::Formatter.info("Installing dependencies...")) + expect(output).to include(Hanami::CLI::Formatter.info("Installing npm packages...")) + expect(output).to include(Hanami::CLI::Formatter.info("Running hanami install...")) fs.chdir(app) do # .gitignore @@ -605,7 +605,7 @@ class Operation < Dry::Operation db/*.sqlite EXPECTED expect(fs.read(".gitignore")).to eq(gitignore) - expect(output).to include("Created .gitignore") + expect(output).to include(Hanami::CLI::Formatter.created(".gitignore")) # .env env = <<~EXPECTED @@ -613,7 +613,7 @@ class Operation < Dry::Operation DATABASE_URL=sqlite://db/#{app}.sqlite EXPECTED expect(fs.read(".env")).to eq(env) - expect(output).to include("Created .env") + expect(output).to include(Hanami::CLI::Formatter.created(".env")) # README.md readme = <<~EXPECTED @@ -634,7 +634,7 @@ class Operation < Dry::Operation - [Hanami API Doc](https://gemdocs.org/gems/hanami/latest) EXPECTED expect(fs.read("README.md")).to eq(readme) - expect(output).to include("Created README.md") + expect(output).to include(Hanami::CLI::Formatter.created("README.md")) # Gemfile hanami_version = Hanami::CLI::Generators::Version.gem_requirement @@ -674,7 +674,7 @@ class Operation < Dry::Operation end EXPECTED expect(fs.read("Gemfile")).to eq(gemfile) - expect(output).to include("Created Gemfile") + expect(output).to include(Hanami::CLI::Formatter.created("Gemfile")) # package.json hanami_npm_version = Hanami::CLI::Generators::Version.npm_package_requirement @@ -689,7 +689,7 @@ class Operation < Dry::Operation } EXPECTED expect(fs.read("package.json")).to eq(package_json) - expect(output).to include("Created package.json") + expect(output).to include(Hanami::CLI::Formatter.created("package.json")) # Procfile.dev procfile = <<~EXPECTED @@ -697,7 +697,7 @@ class Operation < Dry::Operation assets: bundle exec hanami assets watch EXPECTED expect(fs.read("Procfile.dev")).to eq(procfile) - expect(output).to include("Created Procfile.dev") + expect(output).to include(Hanami::CLI::Formatter.created("Procfile.dev")) # Rakefile rakefile = <<~EXPECTED @@ -709,7 +709,7 @@ class Operation < Dry::Operation Rake.add_rakelib "lib/tasks" EXPECTED expect(fs.read("Rakefile")).to eq(rakefile) - expect(output).to include("Created Rakefile") + expect(output).to include(Hanami::CLI::Formatter.created("Rakefile")) # config.ru config_ru = <<~EXPECTED @@ -720,7 +720,7 @@ class Operation < Dry::Operation run Hanami.app EXPECTED expect(fs.read("config.ru")).to eq(config_ru) - expect(output).to include("Created config.ru") + expect(output).to include(Hanami::CLI::Formatter.created("config.ru")) # bin/dev bin_dev = <<~EXPECTED @@ -735,7 +735,7 @@ class Operation < Dry::Operation EXPECTED expect(fs.read("bin/dev")).to eq(bin_dev) expect(fs.executable?("bin/dev")).to be(true) - expect(output).to include("Created bin/dev") + expect(output).to include(Hanami::CLI::Formatter.created("bin/dev")) # config/app.rb hanami_app = <<~EXPECTED @@ -749,7 +749,7 @@ class App < Hanami::App end EXPECTED expect(fs.read("config/app.rb")).to eq(hanami_app) - expect(output).to include("Created config/app.rb") + expect(output).to include(Hanami::CLI::Formatter.created("config/app.rb")) # config/assets.js assets = <<~EXPECTED @@ -772,7 +772,7 @@ class App < Hanami::App }); EXPECTED expect(fs.read("config/assets.js")).to eq(assets) - expect(output).to include("Created config/assets.js") + expect(output).to include(Hanami::CLI::Formatter.created("config/assets.js")) # config/settings.rb settings = <<~EXPECTED @@ -787,7 +787,7 @@ class Settings < Hanami::Settings end EXPECTED expect(fs.read("config/settings.rb")).to eq(settings) - expect(output).to include("Created config/settings.rb") + expect(output).to include(Hanami::CLI::Formatter.created("config/settings.rb")) # config/routes.rb routes = <<~EXPECTED @@ -800,7 +800,7 @@ class Routes < Hanami::Routes end EXPECTED expect(fs.read("config/routes.rb")).to eq(routes) - expect(output).to include("Created config/routes.rb") + expect(output).to include(Hanami::CLI::Formatter.created("config/routes.rb")) # config/puma.rb puma = <<~EXPECTED @@ -853,13 +853,13 @@ class Routes < Hanami::Routes end EXPECTED expect(fs.read("config/puma.rb")).to eq(puma) - expect(output).to include("Created config/puma.rb") + expect(output).to include(Hanami::CLI::Formatter.created("config/puma.rb")) # lib/tasks/.keep tasks_keep = <<~EXPECTED EXPECTED expect(fs.read("lib/tasks/.keep")).to eq(tasks_keep) - expect(output).to include("Created lib/tasks/.keep") + expect(output).to include(Hanami::CLI::Formatter.created("lib/tasks/.keep")) # app/action.rb action = <<~EXPECTED @@ -877,9 +877,9 @@ class Action < Hanami::Action end EXPECTED expect(fs.read("app/action.rb")).to eq(action) - expect(output).to include("Created app/action.rb") + expect(output).to include(Hanami::CLI::Formatter.created("app/action.rb")) expect(fs.read("app/actions/.keep")).to eq("") - expect(output).to include("Created app/actions/.keep") + expect(output).to include(Hanami::CLI::Formatter.created("app/actions/.keep")) # app/view.rb view = <<~RUBY @@ -894,7 +894,7 @@ class View < Hanami::View end RUBY expect(fs.read("app/view.rb")).to eq(view) - expect(output).to include("Created app/view.rb") + expect(output).to include(Hanami::CLI::Formatter.created("app/view.rb")) # app/views/helpers.rb helpers = <<~RUBY @@ -910,7 +910,7 @@ module Helpers end RUBY expect(fs.read("app/views/helpers.rb")).to eq(helpers) - expect(output).to include("Created app/views/helpers.rb") + expect(output).to include(Hanami::CLI::Formatter.created("app/views/helpers.rb")) # app/templates/layouts/app.html.erb layout = <<~ERB @@ -930,14 +930,14 @@ module Helpers ERB expect(fs.read("app/templates/layouts/app.html.erb")).to eq(layout) - expect(output).to include("Created app/templates/layouts/app.html.erb") + expect(output).to include(Hanami::CLI::Formatter.created("app/templates/layouts/app.html.erb")) # app/assets/js/app.js app_js = <<~EXPECTED import "../css/app.css"; EXPECTED expect(fs.read("app/assets/js/app.js")).to eq(app_js) - expect(output).to include("Created app/assets/js/app.js") + expect(output).to include(Hanami::CLI::Formatter.created("app/assets/js/app.js")) # app/assets/css/app.css app_css = <<~EXPECTED @@ -948,7 +948,7 @@ module Helpers } EXPECTED expect(fs.read("app/assets/css/app.css")).to eq(app_css) - expect(output).to include("Created app/assets/css/app.css") + expect(output).to include(Hanami::CLI::Formatter.created("app/assets/css/app.css")) # app/assets/images/favicon.ico expect(fs.exist?("app/assets/images/favicon.ico")).to be(true) @@ -967,9 +967,9 @@ class Relation < Hanami::DB::Relation end EXPECTED expect(fs.read("app/db/relation.rb")).to eq(relation) - expect(output).to include("Created app/db/relation.rb") + expect(output).to include(Hanami::CLI::Formatter.created("app/db/relation.rb")) expect(fs.read("app/relations/.keep")).to eq("") - expect(output).to include("Created app/relations/.keep") + expect(output).to include(Hanami::CLI::Formatter.created("app/relations/.keep")) # app/db/repo.rb repo = <<~EXPECTED @@ -985,9 +985,9 @@ class Repo < Hanami::DB::Repo end EXPECTED expect(fs.read("app/db/repo.rb")).to eq(repo) - expect(output).to include("Created app/db/repo.rb") + expect(output).to include(Hanami::CLI::Formatter.created("app/db/repo.rb")) expect(fs.read("app/repos/.keep")).to eq("") - expect(output).to include("Created app/repos/.keep") + expect(output).to include(Hanami::CLI::Formatter.created("app/repos/.keep")) # app/db/struct.rb struct = <<~EXPECTED @@ -1003,9 +1003,9 @@ class Struct < Hanami::DB::Struct end EXPECTED expect(fs.read("app/db/struct.rb")).to eq(struct) - expect(output).to include("Created app/db/struct.rb") + expect(output).to include(Hanami::CLI::Formatter.created("app/db/struct.rb")) expect(fs.read("app/structs/.keep")).to eq("") - expect(output).to include("Created app/structs/.keep") + expect(output).to include(Hanami::CLI::Formatter.created("app/structs/.keep")) seeds = <<~EXPECTED # This seeds file should create the database records required to run the app. @@ -1025,13 +1025,13 @@ class Struct < Hanami::DB::Struct # categories.insert(title: "General") EXPECTED expect(fs.read("config/db/seeds.rb")).to eq(seeds) - expect(output).to include("Created config/db/seeds.rb") + expect(output).to include(Hanami::CLI::Formatter.created("config/db/seeds.rb")) expect(fs.read("config/db/migrate/.keep")).to eq("") - expect(output).to include("Created config/db/migrate/.keep") + expect(output).to include(Hanami::CLI::Formatter.created("config/db/migrate/.keep")) expect(fs.read("db/.keep")).to eq("") - expect(output).to include("Created db/.keep") + expect(output).to include(Hanami::CLI::Formatter.created("db/.keep")) # lib/bookshelf/types.rb types = <<~EXPECTED @@ -1048,7 +1048,7 @@ module Types end EXPECTED expect(fs.read("lib/#{app}/types.rb")).to eq(types) - expect(output).to include("Created lib/bookshelf/types.rb") + expect(output).to include(Hanami::CLI::Formatter.created("lib/bookshelf/types.rb")) # public/ error pages expect(fs.read("public/404.html")).to include %(The page you were looking for doesn’t exist (404)) @@ -1412,7 +1412,7 @@ class App < Hanami::App subject.call(app: app, **kwargs) expect(fs.directory?(app)).to be(true) - expect(output).to include("Running bundle binstubs hanami-cli rake...") + expect(output).to include(Hanami::CLI::Formatter.info("Running bundle binstubs hanami-cli rake...")) end it "initializes a git repository" do @@ -1438,6 +1438,6 @@ class App < Hanami::App subject.call(app: app, **kwargs) expect(fs.directory?(app)).to be(true) - expect(output).to include("Initializing git repository...") + expect(output).to include(Hanami::CLI::Formatter.info("Initializing git repository...")) end end diff --git a/spec/unit/hanami/cli/formatter_spec.rb b/spec/unit/hanami/cli/formatter_spec.rb new file mode 100644 index 00000000..92cec8e9 --- /dev/null +++ b/spec/unit/hanami/cli/formatter_spec.rb @@ -0,0 +1,427 @@ +# frozen_string_literal: true + +RSpec.describe Hanami::CLI::Formatter do + describe "COLORS" do + it "defines ANSI color codes" do + expect(described_class::COLORS).to eq({ + reset: "\e[0m", + bold: "\e[1m", + green: "\e[32m", + blue: "\e[34m", + cyan: "\e[36m", + yellow: "\e[33m", + red: "\e[31m", + gray: "\e[90m" + }) + end + + it "is frozen" do + expect(described_class::COLORS).to be_frozen + end + end + + describe "ICONS" do + it "defines icons for different operations" do + expect(described_class::ICONS).to eq({ + create: "✓", + update: "↻", + info: "→", + warning: "⚠", + error: "✗", + success: "✓" + }) + end + + it "is frozen" do + expect(described_class::ICONS).to be_frozen + end + end + + describe ".colorize" do + context "when stdout is a tty" do + before do + allow($stdout).to receive(:tty?).and_return(true) + end + + it "wraps text with color codes" do + result = described_class.colorize("hello", :green) + expect(result).to eq("\e[32mhello\e[0m") + end + + it "handles different colors" do + expect(described_class.colorize("text", :red)).to eq("\e[31mtext\e[0m") + expect(described_class.colorize("text", :blue)).to eq("\e[34mtext\e[0m") + expect(described_class.colorize("text", :yellow)).to eq("\e[33mtext\e[0m") + expect(described_class.colorize("text", :cyan)).to eq("\e[36mtext\e[0m") + expect(described_class.colorize("text", :gray)).to eq("\e[90mtext\e[0m") + expect(described_class.colorize("text", :bold)).to eq("\e[1mtext\e[0m") + end + + it "handles empty text" do + result = described_class.colorize("", :green) + expect(result).to eq("\e[32m\e[0m") + end + + it "handles nil color gracefully" do + result = described_class.colorize("text", nil) + expect(result).to eq("text\e[0m") + end + end + + context "when stdout is not a tty" do + before do + allow($stdout).to receive(:tty?).and_return(false) + end + + it "returns text without color codes" do + result = described_class.colorize("hello", :green) + expect(result).to eq("hello") + end + + it "handles empty text" do + result = described_class.colorize("", :green) + expect(result).to eq("") + end + end + end + + describe ".created" do + context "when stdout is a tty" do + before do + allow($stdout).to receive(:tty?).and_return(true) + end + + it "formats a create message with green color and icon" do + result = described_class.created("app/models/user.rb") + expect(result).to eq(" \e[32m✓\e[0m \e[32mcreate\e[0m app/models/user.rb") + end + + it "handles paths with spaces" do + result = described_class.created("my app/user.rb") + expect(result).to eq(" \e[32m✓\e[0m \e[32mcreate\e[0m my app/user.rb") + end + end + + context "when stdout is not a tty" do + before do + allow($stdout).to receive(:tty?).and_return(false) + end + + it "formats a create message without colors" do + result = described_class.created("app/models/user.rb") + expect(result).to eq(" ✓ create app/models/user.rb") + end + end + end + + describe ".created_directory" do + context "when stdout is a tty" do + before do + allow($stdout).to receive(:tty?).and_return(true) + end + + it "formats a create directory message with green color and icon" do + result = described_class.created_directory("app/models") + expect(result).to eq("\e[32m✓\e[0m \e[32mcreate directory\e[0m app/models") + end + + it "handles directory paths with spaces" do + result = described_class.created_directory("my app/models") + expect(result).to eq("\e[32m✓\e[0m \e[32mcreate directory\e[0m my app/models") + end + end + + context "when stdout is not a tty" do + before do + allow($stdout).to receive(:tty?).and_return(false) + end + + it "formats a create directory message without colors" do + result = described_class.created_directory("app/models") + expect(result).to eq("✓ create directory app/models") + end + end + end + + describe ".updated" do + context "when stdout is a tty" do + before do + allow($stdout).to receive(:tty?).and_return(true) + end + + it "formats an update message with cyan color and icon" do + result = described_class.updated("config/routes.rb") + expect(result).to eq(" \e[36m↻\e[0m \e[36mupdate\e[0m config/routes.rb") + end + + it "handles paths with spaces" do + result = described_class.updated("my config/routes.rb") + expect(result).to eq(" \e[36m↻\e[0m \e[36mupdate\e[0m my config/routes.rb") + end + end + + context "when stdout is not a tty" do + before do + allow($stdout).to receive(:tty?).and_return(false) + end + + it "formats an update message without colors" do + result = described_class.updated("config/routes.rb") + expect(result).to eq(" ↻ update config/routes.rb") + end + end + end + + describe ".info" do + context "when stdout is a tty" do + before do + allow($stdout).to receive(:tty?).and_return(true) + end + + it "formats an info message with blue color and icon" do + result = described_class.info("Starting server...") + expect(result).to eq("\e[34m→\e[0m Starting server...") + end + + it "handles empty text" do + result = described_class.info("") + expect(result).to eq("\e[34m→\e[0m ") + end + + it "handles multiline text" do + result = described_class.info("Line 1\nLine 2") + expect(result).to eq("\e[34m→\e[0m Line 1\nLine 2") + end + end + + context "when stdout is not a tty" do + before do + allow($stdout).to receive(:tty?).and_return(false) + end + + it "formats an info message without colors" do + result = described_class.info("Starting server...") + expect(result).to eq("→ Starting server...") + end + end + end + + describe ".success" do + context "when stdout is a tty" do + before do + allow($stdout).to receive(:tty?).and_return(true) + end + + it "formats a success message with green color and icon" do + result = described_class.success("Application created successfully!") + expect(result).to eq("\e[32m✓\e[0m \e[32mApplication created successfully!\e[0m") + end + + it "handles empty text" do + result = described_class.success("") + expect(result).to eq("\e[32m✓\e[0m \e[32m\e[0m") + end + + it "handles multiline text" do + result = described_class.success("Success!\nAll done.") + expect(result).to eq("\e[32m✓\e[0m \e[32mSuccess!\nAll done.\e[0m") + end + end + + context "when stdout is not a tty" do + before do + allow($stdout).to receive(:tty?).and_return(false) + end + + it "formats a success message without colors" do + result = described_class.success("Application created successfully!") + expect(result).to eq("✓ Application created successfully!") + end + end + end + + describe ".warning" do + context "when stdout is a tty" do + before do + allow($stdout).to receive(:tty?).and_return(true) + end + + it "formats a warning message with yellow color and icon" do + result = described_class.warning("This is deprecated") + expect(result).to eq("\e[33m⚠\e[0m \e[33mwarning\e[0m This is deprecated") + end + + it "handles empty text" do + result = described_class.warning("") + expect(result).to eq("\e[33m⚠\e[0m \e[33mwarning\e[0m ") + end + + it "handles multiline text" do + result = described_class.warning("Warning!\nBe careful.") + expect(result).to eq("\e[33m⚠\e[0m \e[33mwarning\e[0m Warning!\nBe careful.") + end + end + + context "when stdout is not a tty" do + before do + allow($stdout).to receive(:tty?).and_return(false) + end + + it "formats a warning message without colors" do + result = described_class.warning("This is deprecated") + expect(result).to eq("⚠ warning This is deprecated") + end + end + end + + describe ".error" do + context "when stdout is a tty" do + before do + allow($stdout).to receive(:tty?).and_return(true) + end + + it "formats an error message with red color and icon" do + result = described_class.error("Something went wrong") + expect(result).to eq("\e[31m✗\e[0m \e[31merror\e[0m Something went wrong") + end + + it "handles empty text" do + result = described_class.error("") + expect(result).to eq("\e[31m✗\e[0m \e[31merror\e[0m ") + end + + it "handles multiline text" do + result = described_class.error("Error!\nCheck the logs.") + expect(result).to eq("\e[31m✗\e[0m \e[31merror\e[0m Error!\nCheck the logs.") + end + end + + context "when stdout is not a tty" do + before do + allow($stdout).to receive(:tty?).and_return(false) + end + + it "formats an error message without colors" do + result = described_class.error("Something went wrong") + expect(result).to eq("✗ error Something went wrong") + end + end + end + + describe ".header" do + context "when stdout is a tty" do + before do + allow($stdout).to receive(:tty?).and_return(true) + end + + it "formats a header with bold text and newline prefix" do + result = described_class.header("Configuration") + expect(result).to eq("\n\e[1mConfiguration\e[0m") + end + + it "handles empty text" do + result = described_class.header("") + expect(result).to eq("\n\e[1m\e[0m") + end + + it "handles multiline text" do + result = described_class.header("Header\nSubheader") + expect(result).to eq("\n\e[1mHeader\nSubheader\e[0m") + end + end + + context "when stdout is not a tty" do + before do + allow($stdout).to receive(:tty?).and_return(false) + end + + it "formats a header without colors but with newline prefix" do + result = described_class.header("Configuration") + expect(result).to eq("\nConfiguration") + end + end + end + + describe ".dim" do + it "returns the text unchanged" do + result = described_class.dim("secondary text") + expect(result).to eq("secondary text") + end + + it "handles empty text" do + result = described_class.dim("") + expect(result).to eq("") + end + + it "handles multiline text" do + result = described_class.dim("Line 1\nLine 2") + expect(result).to eq("Line 1\nLine 2") + end + + it "handles nil input" do + result = described_class.dim(nil) + expect(result).to be_nil + end + end + + describe "module behavior" do + it "is a module" do + expect(described_class).to be_a(Module) + end + + it "has module_function methods" do + expect(described_class).to respond_to(:colorize) + expect(described_class).to respond_to(:created) + expect(described_class).to respond_to(:updated) + expect(described_class).to respond_to(:info) + expect(described_class).to respond_to(:success) + expect(described_class).to respond_to(:warning) + expect(described_class).to respond_to(:error) + expect(described_class).to respond_to(:header) + expect(described_class).to respond_to(:dim) + end + end + + describe "integration scenarios" do + context "when stdout is a tty" do + before do + allow($stdout).to receive(:tty?).and_return(true) + end + + it "formats a complete workflow with different message types" do + messages = [ + described_class.header("Creating new application"), + described_class.created_directory("my_app"), + described_class.created("my_app/config.ru"), + described_class.updated("my_app/Gemfile"), + described_class.info("Installing dependencies..."), + described_class.success("Application created successfully!"), + described_class.warning("Remember to run bundle install"), + described_class.dim("Additional notes here") + ] + + expect(messages).to all(be_a(String)) + expect(messages.join("\n")).to include("Creating new application") + expect(messages.join("\n")).to include("my_app") + expect(messages.join("\n")).to include("✓") + expect(messages.join("\n")).to include("↻") + expect(messages.join("\n")).to include("→") + expect(messages.join("\n")).to include("⚠") + end + end + + context "when stdout is not a tty" do + before do + allow($stdout).to receive(:tty?).and_return(false) + end + + it "formats messages without ANSI codes" do + result = described_class.created("test.rb") + expect(result).not_to include("\e[") + expect(result).to include("✓") + expect(result).to include("create") + expect(result).to include("test.rb") + end + end + end +end From 3acbdd3627b5ea4d58ab48bb30e08d2c9706ffd7 Mon Sep 17 00:00:00 2001 From: Andrea Fomera Date: Thu, 23 Oct 2025 21:03:54 -0600 Subject: [PATCH 4/5] Fix failing specs for the formatter changes --- .../cli/commands/app/generate/action_spec.rb | 116 +++++++++--------- .../commands/app/generate/component_spec.rb | 18 +-- .../commands/app/generate/migration_spec.rb | 8 +- .../commands/app/generate/operation_spec.rb | 10 +- .../cli/commands/app/generate/part_spec.rb | 14 +-- .../commands/app/generate/relation_spec.rb | 16 +-- .../cli/commands/app/generate/repo_spec.rb | 12 +- .../cli/commands/app/generate/slice_spec.rb | 36 +++--- .../cli/commands/app/generate/struct_spec.rb | 10 +- .../cli/commands/app/generate/view_spec.rb | 12 +- 10 files changed, 126 insertions(+), 126 deletions(-) diff --git a/spec/unit/hanami/cli/commands/app/generate/action_spec.rb b/spec/unit/hanami/cli/commands/app/generate/action_spec.rb index db997d78..7e828ac6 100644 --- a/spec/unit/hanami/cli/commands/app/generate/action_spec.rb +++ b/spec/unit/hanami/cli/commands/app/generate/action_spec.rb @@ -33,10 +33,10 @@ def error_output = err.string.chomp within_application_directory do generate_action - expect(output).to include("Updated config/routes.rb") - expect(output).to include("Created app/actions/#{controller}/#{action}.rb") - expect(output).to include("Created app/views/#{controller}/#{action}.rb") - expect(output).to include("Created app/templates/#{controller}/#{action}.html.erb") + expect(output).to include(" \e[36m↻\e[0m \e[36mupdate\e[0m config/routes.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/actions/#{controller}/#{action}.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/views/#{controller}/#{action}.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/templates/#{controller}/#{action}.html.erb") end end end @@ -122,7 +122,7 @@ class Routes < Hanami::Routes # route expect(fs.read("config/routes.rb")).to eq(routes) - expect(output).to include("Updated config/routes.rb") + expect(output).to include(" \e[36m↻\e[0m \e[36mupdate\e[0m config/routes.rb") # action action_file = <<~EXPECTED @@ -142,7 +142,7 @@ def handle(request, response) EXPECTED expect(fs.read("app/actions/#{controller}/#{action}.rb")).to eq(action_file) - expect(output).to include("Created app/actions/#{controller}/#{action}.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/actions/#{controller}/#{action}.rb") expect(fs.directory?("app/views/#{controller}")).to eq(false) expect(fs.exist?("app/views/#{controller}/#{action}.rb")).to eq(false) @@ -177,31 +177,31 @@ def handle(request, response) within_application_directory do subject.call(name: "users.index") expect(fs.read("config/routes.rb")).to match(%(get "/users", to: "users.index")) - expect(output).to include("Updated config/routes.rb") + expect(output).to include(" \e[36m↻\e[0m \e[36mupdate\e[0m config/routes.rb") subject.call(name: "users.new") expect(fs.read("config/routes.rb")).to match(%(get "/users/new", to: "users.new")) - expect(output).to include("Updated config/routes.rb") + expect(output).to include(" \e[36m↻\e[0m \e[36mupdate\e[0m config/routes.rb") subject.call(name: "users.create") expect(fs.read("config/routes.rb")).to match(%(post "/users", to: "users.create")) - expect(output).to include("Updated config/routes.rb") + expect(output).to include(" \e[36m↻\e[0m \e[36mupdate\e[0m config/routes.rb") subject.call(name: "users.edit") expect(fs.read("config/routes.rb")).to match(%(get "/users/:id/edit", to: "users.edit")) - expect(output).to include("Updated config/routes.rb") + expect(output).to include(" \e[36m↻\e[0m \e[36mupdate\e[0m config/routes.rb") subject.call(name: "users.update") expect(fs.read("config/routes.rb")).to match(%(patch "/users/:id", to: "users.update")) - expect(output).to include("Updated config/routes.rb") + expect(output).to include(" \e[36m↻\e[0m \e[36mupdate\e[0m config/routes.rb") subject.call(name: "users.show") expect(fs.read("config/routes.rb")).to match(%(get "/users/:id", to: "users.show")) - expect(output).to include("Updated config/routes.rb") + expect(output).to include(" \e[36m↻\e[0m \e[36mupdate\e[0m config/routes.rb") subject.call(name: "users.destroy") expect(fs.read("config/routes.rb")).to match(%(delete "/users/:id", to: "users.destroy")) - expect(output).to include("Updated config/routes.rb") + expect(output).to include(" \e[36m↻\e[0m \e[36mupdate\e[0m config/routes.rb") end end @@ -209,7 +209,7 @@ def handle(request, response) within_application_directory do subject.call(name: "talent.apply", url_path: "/talent/apply") expect(fs.read("config/routes.rb")).to match(%(get "/talent/apply", to: "talent.apply")) - expect(output).to include("Updated config/routes.rb") + expect(output).to include(" \e[36m↻\e[0m \e[36mupdate\e[0m config/routes.rb") end end @@ -217,7 +217,7 @@ def handle(request, response) within_application_directory do subject.call(name: action_name, url_path: "/people") expect(fs.read("config/routes.rb")).to match(%(get "/people", to: "users.index")) - expect(output).to include("Updated config/routes.rb") + expect(output).to include(" \e[36m↻\e[0m \e[36mupdate\e[0m config/routes.rb") end end @@ -225,7 +225,7 @@ def handle(request, response) within_application_directory do subject.call(name: action_name, http_method: "put") expect(fs.read("config/routes.rb")).to match(%(put "/users", to: "users.index")) - expect(output).to include("Updated config/routes.rb") + expect(output).to include(" \e[36m↻\e[0m \e[36mupdate\e[0m config/routes.rb") end end @@ -235,7 +235,7 @@ def handle(request, response) subject.call(name: action_name, skip_view: true) expect(fs.read("config/routes.rb")).to match(%(get "/api/users/thing", to: "api.users.thing")) - expect(output).to include("Updated config/routes.rb") + expect(output).to include(" \e[36m↻\e[0m \e[36mupdate\e[0m config/routes.rb") action_file = <<~EXPECTED # frozen_string_literal: true @@ -256,7 +256,7 @@ def handle(request, response) EXPECTED expect(fs.read("app/actions/api/users/thing.rb")).to eq(action_file) - expect(output).to include("Created app/actions/api/users/thing.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/actions/api/users/thing.rb") end end @@ -337,7 +337,7 @@ class Routes < Hanami::Routes # route expect(fs.read("config/routes.rb")).to eq(routes) - expect(output).to include("Updated config/routes.rb") + expect(output).to include(" \e[36m↻\e[0m \e[36mupdate\e[0m config/routes.rb") # action action_file = <<~EXPECTED @@ -356,7 +356,7 @@ def handle(request, response) EXPECTED expect(fs.read("app/actions/#{controller}/#{action}.rb")).to eq(action_file) - expect(output).to include("Created app/actions/#{controller}/#{action}.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/actions/#{controller}/#{action}.rb") # view view_file = <<~EXPECTED @@ -373,7 +373,7 @@ class #{inflector.camelize(action)} < #{inflector.camelize(app)}::View EXPECTED expect(fs.read("app/views/#{controller}/#{action}.rb")).to eq(view_file) - expect(output).to include("Created app/views/#{controller}/#{action}.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/views/#{controller}/#{action}.rb") # template expect(fs.directory?("app/templates/#{controller}")).to be(true) @@ -383,7 +383,7 @@ class #{inflector.camelize(action)} < #{inflector.camelize(app)}::View EXPECTED expect(fs.read("app/templates/#{controller}/#{action}.html.erb")).to eq(template_file) - expect(output).to include("Created app/templates/#{controller}/#{action}.html.erb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/templates/#{controller}/#{action}.html.erb") end end @@ -394,7 +394,7 @@ class #{inflector.camelize(action)} < #{inflector.camelize(app)}::View subject.call(name: action_name) expect(fs.read("config/routes.rb")).to match(%(get "/api/users/thing", to: "api.users.thing")) - expect(output).to include("Updated config/routes.rb") + expect(output).to include(" \e[36m↻\e[0m \e[36mupdate\e[0m config/routes.rb") action_file = <<~EXPECTED # frozen_string_literal: true @@ -414,7 +414,7 @@ def handle(request, response) EXPECTED expect(fs.read("app/actions/api/users/thing.rb")).to eq(action_file) - expect(output).to include("Created app/actions/api/users/thing.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/actions/api/users/thing.rb") end end end @@ -457,7 +457,7 @@ def handle(request, response) EXPECTED expect(fs.read("app/actions/#{controller}/#{action}.rb")).to eq(action_file) - expect(output).to include("Created app/actions/#{controller}/#{action}.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/actions/#{controller}/#{action}.rb") # view view_file = <<~EXPECTED @@ -474,7 +474,7 @@ class #{inflector.camelize(action)} < #{inflector.camelize(app)}::View EXPECTED expect(fs.read("app/views/#{controller}/#{action}.rb")).to eq(view_file) - expect(output).to include("Created app/views/#{controller}/#{action}.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/views/#{controller}/#{action}.rb") # template expect(fs.directory?("app/templates/#{controller}")).to be(true) @@ -484,7 +484,7 @@ class #{inflector.camelize(action)} < #{inflector.camelize(app)}::View EXPECTED expect(fs.read("app/templates/#{controller}/#{action}.html.erb")).to eq(template_file) - expect(output).to include("Created app/templates/#{controller}/#{action}.html.erb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/templates/#{controller}/#{action}.html.erb") end end @@ -569,7 +569,7 @@ class Routes < Hanami::Routes # route expect(fs.read("config/routes.rb")).to eq(expected_routes) - expect(output).to include("Updated config/routes.rb") + expect(output).to include(" \e[36m↻\e[0m \e[36mupdate\e[0m config/routes.rb") expected_action = <<~CODE # frozen_string_literal: true @@ -586,7 +586,7 @@ def handle(request, response) end CODE expect(fs.read("app/actions/users/create.rb")).to eq(expected_action) - expect(output).to include("Created app/actions/users/create.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/actions/users/create.rb") expect(fs.exist?("app/views/users/create.rb")).to be(false) expect(fs.exist?("app/templates/users/create.html.erb")).to be(false) @@ -631,7 +631,7 @@ class Routes < Hanami::Routes # route expect(fs.read("config/routes.rb")).to eq(expected_routes) - expect(output).to include("Updated config/routes.rb") + expect(output).to include(" \e[36m↻\e[0m \e[36mupdate\e[0m config/routes.rb") expected_action = <<~CODE # frozen_string_literal: true @@ -648,7 +648,7 @@ def handle(request, response) end CODE expect(fs.read("app/actions/users/create.rb")).to eq(expected_action) - expect(output).to include("Created app/actions/users/create.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/actions/users/create.rb") expected_view = <<~CODE # frozen_string_literal: true @@ -663,14 +663,14 @@ class Create < #{app}::View end CODE expect(fs.read("app/views/users/create.rb")).to eq(expected_view) - expect(output).to include("Created app/views/users/create.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/views/users/create.rb") expected_template = <<~EXPECTED

#{inflector.camelize(app)}::Views::Users::Create

EXPECTED expect(fs.read("app/templates/users/create.html.erb")).to eq(expected_template) - expect(output).to include("Created app/templates/users/create.html.erb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/templates/users/create.html.erb") end end @@ -708,7 +708,7 @@ class Routes < Hanami::Routes # route expect(fs.read("config/routes.rb")).to eq(expected_routes) - expect(output).to include("Updated config/routes.rb") + expect(output).to include(" \e[36m↻\e[0m \e[36mupdate\e[0m config/routes.rb") expected_action = <<~CODE # frozen_string_literal: true @@ -726,7 +726,7 @@ def handle(request, response) end CODE expect(fs.read("app/actions/users/create.rb")).to eq(expected_action) - expect(output).to include("Created app/actions/users/create.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/actions/users/create.rb") expect(fs.exist?("app/views/users/create.rb")).to be(false) expect(fs.exist?("app/templates/users/create.html.erb")).to be(false) @@ -809,7 +809,7 @@ class Routes < Hanami::Routes # route expect(fs.read("config/routes.rb")).to eq(expected_routes) - expect(output).to include("Updated config/routes.rb") + expect(output).to include(" \e[36m↻\e[0m \e[36mupdate\e[0m config/routes.rb") expected_action = <<~CODE # frozen_string_literal: true @@ -826,7 +826,7 @@ def handle(request, response) end CODE expect(fs.read("app/actions/users/update.rb")).to eq(expected_action) - expect(output).to include("Created app/actions/users/update.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/actions/users/update.rb") expect(fs.exist?("app/views/users/update.rb")).to be(false) expect(fs.exist?("app/templates/users/update.html.erb")).to be(false) @@ -871,7 +871,7 @@ class Routes < Hanami::Routes # route expect(fs.read("config/routes.rb")).to eq(expected_routes) - expect(output).to include("Updated config/routes.rb") + expect(output).to include(" \e[36m↻\e[0m \e[36mupdate\e[0m config/routes.rb") expected_action = <<~CODE # frozen_string_literal: true @@ -888,7 +888,7 @@ def handle(request, response) end CODE expect(fs.read("app/actions/users/update.rb")).to eq(expected_action) - expect(output).to include("Created app/actions/users/update.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/actions/users/update.rb") expected_view = <<~CODE # frozen_string_literal: true @@ -903,14 +903,14 @@ class Update < #{app}::View end CODE expect(fs.read("app/views/users/update.rb")).to eq(expected_view) - expect(output).to include("Created app/views/users/update.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/views/users/update.rb") expected_template = <<~EXPECTED

#{inflector.camelize(app)}::Views::Users::Update

EXPECTED expect(fs.read("app/templates/users/update.html.erb")).to eq(expected_template) - expect(output).to include("Created app/templates/users/update.html.erb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/templates/users/update.html.erb") end end @@ -948,7 +948,7 @@ class Routes < Hanami::Routes # route expect(fs.read("config/routes.rb")).to eq(expected_routes) - expect(output).to include("Updated config/routes.rb") + expect(output).to include(" \e[36m↻\e[0m \e[36mupdate\e[0m config/routes.rb") expected_action = <<~CODE # frozen_string_literal: true @@ -966,7 +966,7 @@ def handle(request, response) end CODE expect(fs.read("app/actions/users/update.rb")).to eq(expected_action) - expect(output).to include("Created app/actions/users/update.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/actions/users/update.rb") expect(fs.exist?("app/views/users/update.rb")).to be(false) expect(fs.exist?("app/templates/users/update.html.erb")).to be(false) @@ -1015,12 +1015,12 @@ class Routes < Hanami::Routes # route expect(fs.read("config/routes.rb")).to eq(routes) - expect(output).to include("Updated config/routes.rb") - expect(output).to include("Created slices/#{slice}/actions/#{controller}/") + expect(output).to include(" \e[36m↻\e[0m \e[36mupdate\e[0m config/routes.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/#{slice}/actions/#{controller}/") # action expect(fs.directory?("slices/#{slice}/actions/#{controller}")).to be(true) - expect(output).to include("Created slices/#{slice}/actions/#{controller}/") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/#{slice}/actions/#{controller}/") action_file = <<~EXPECTED # frozen_string_literal: true @@ -1038,7 +1038,7 @@ def handle(request, response) end EXPECTED expect(fs.read("slices/#{slice}/actions/#{controller}/#{action}.rb")).to eq(action_file) - expect(output).to include("Created slices/#{slice}/actions/#{controller}/#{action}.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/#{slice}/actions/#{controller}/#{action}.rb") # view expect(fs.directory?("slices/#{slice}/views/#{controller}")).to be(false) @@ -1225,12 +1225,12 @@ class Routes < Hanami::Routes # route expect(fs.read("config/routes.rb")).to eq(routes) - expect(output).to include("Updated config/routes.rb") - expect(output).to include("Created slices/#{slice}/actions/#{controller}/") + expect(output).to include(" \e[36m↻\e[0m \e[36mupdate\e[0m config/routes.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/#{slice}/actions/#{controller}/") # action expect(fs.directory?("slices/#{slice}/actions/#{controller}")).to be(true) - expect(output).to include("Created slices/#{slice}/actions/#{controller}/") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/#{slice}/actions/#{controller}/") action_file = <<~EXPECTED # frozen_string_literal: true @@ -1247,11 +1247,11 @@ def handle(request, response) end EXPECTED expect(fs.read("slices/#{slice}/actions/#{controller}/#{action}.rb")).to eq(action_file) - expect(output).to include("Created slices/#{slice}/actions/#{controller}/#{action}.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/#{slice}/actions/#{controller}/#{action}.rb") # view expect(fs.directory?("slices/#{slice}/views/#{controller}")).to be(true) - expect(output).to include("Created slices/#{slice}/views/#{controller}/") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/#{slice}/views/#{controller}/") view_file = <<~EXPECTED # frozen_string_literal: true @@ -1266,17 +1266,17 @@ class #{inflector.camelize(action)} < #{inflector.camelize(slice)}::View end EXPECTED expect(fs.read("slices/#{slice}/views/#{controller}/#{action}.rb")).to eq(view_file) - expect(output).to include("Created slices/#{slice}/views/#{controller}/#{action}.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/#{slice}/views/#{controller}/#{action}.rb") # template expect(fs.directory?("slices/#{slice}/templates/#{controller}")).to be(true) - expect(output).to include("Created slices/#{slice}/templates/#{controller}/") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/#{slice}/templates/#{controller}/") template_file = <<~EXPECTED

#{inflector.camelize(slice)}::Views::#{inflector.camelize(controller)}::#{inflector.camelize(action)}

EXPECTED expect(fs.read("slices/#{slice}/templates/#{controller}/#{action}.html.erb")).to eq(template_file) - expect(output).to include("Created slices/#{slice}/templates/#{controller}/#{action}.html.erb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/#{slice}/templates/#{controller}/#{action}.html.erb") end end @@ -1356,8 +1356,8 @@ class Routes < Hanami::Routes # route expect(fs.read("config/routes.rb")).to eq(expected_routes) - expect(output).to include("Updated config/routes.rb") - expect(output).to include("Created slices/#{slice}/actions/#{controller}/") + expect(output).to include(" \e[36m↻\e[0m \e[36mupdate\e[0m config/routes.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/#{slice}/actions/#{controller}/") # action expected_action = <<~EXPECTED @@ -1375,7 +1375,7 @@ def handle(request, response) end EXPECTED expect(fs.read("slices/#{slice}/actions/#{controller}/#{action}.rb")).to eq(expected_action) - expect(output).to include("Created slices/#{slice}/actions/#{controller}/#{action}.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/#{slice}/actions/#{controller}/#{action}.rb") # view expect(output).to_not include("Created slices/#{slice}/views/#{controller}/#{action}.rb") diff --git a/spec/unit/hanami/cli/commands/app/generate/component_spec.rb b/spec/unit/hanami/cli/commands/app/generate/component_spec.rb index d56714da..3535cd8a 100644 --- a/spec/unit/hanami/cli/commands/app/generate/component_spec.rb +++ b/spec/unit/hanami/cli/commands/app/generate/component_spec.rb @@ -38,7 +38,7 @@ class SendWelcomeEmail EXPECTED expect(fs.read("app/operations/send_welcome_email.rb")).to eq(component) - expect(output).to include("Created app/operations/send_welcome_email.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/operations/send_welcome_email.rb") end context "with existing file" do @@ -79,7 +79,7 @@ class SendWelcomeEmail EXPECTED expect(fs.read("app/operations/user/mailing/send_welcome_email.rb")).to eq(component) - expect(output).to include("Created app/operations/user/mailing/send_welcome_email.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/operations/user/mailing/send_welcome_email.rb") end context "with existing file" do @@ -119,7 +119,7 @@ class WelcomeEmail EXPECTED expect(fs.read("slices/main/renderers/welcome_email.rb")).to eq(component) - expect(output).to include("Created slices/main/renderers/welcome_email.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/main/renderers/welcome_email.rb") end context "with existing file" do @@ -161,7 +161,7 @@ class WelcomeEmail EXPECTED expect(fs.read("slices/main/renderers/user/mailing/welcome_email.rb")).to eq(component) - expect(output).to include("Created slices/main/renderers/user/mailing/welcome_email.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/main/renderers/user/mailing/welcome_email.rb") end context "with existing file" do @@ -205,7 +205,7 @@ class SendWelcomeEmail EXPECTED expect(fs.read("app/operations/send_welcome_email.rb")).to eq(component) - expect(output).to include("Created app/operations/send_welcome_email.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/operations/send_welcome_email.rb") end end @@ -223,7 +223,7 @@ class CreateEntry EXPECTED expect(fs.read("app/create_entry.rb")).to eq(component) - expect(output).to include("Created app/create_entry.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/create_entry.rb") end context "when nested" do @@ -242,7 +242,7 @@ class CreateEntry EXPECTED expect(fs.read("app/services/create_entry.rb")).to eq(component) - expect(output).to include("Created app/services/create_entry.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/services/create_entry.rb") end end @@ -262,7 +262,7 @@ class CreateEntry EXPECTED expect(fs.read("app/services/create_entry.rb")).to eq(component) - expect(output).to include("Created app/services/create_entry.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/services/create_entry.rb") end end @@ -282,7 +282,7 @@ class CreateEntry EXPECTED expect(fs.read("app/services/create_entry.rb")).to eq(component) - expect(output).to include("Created app/services/create_entry.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/services/create_entry.rb") end end end diff --git a/spec/unit/hanami/cli/commands/app/generate/migration_spec.rb b/spec/unit/hanami/cli/commands/app/generate/migration_spec.rb index 244bb41c..1ad381c8 100644 --- a/spec/unit/hanami/cli/commands/app/generate/migration_spec.rb +++ b/spec/unit/hanami/cli/commands/app/generate/migration_spec.rb @@ -40,21 +40,21 @@ def error_output = err.string.chomp subject.call(name: "create_posts") expect(fs.read("config/db/migrate/20240713140600_create_posts.rb")).to eq migration_file_contents - expect(output).to eq("Created config/db/migrate/20240713140600_create_posts.rb") + expect(output).to eq("\e[32m✓\e[0m \e[32mcreate\e[0m config/db/migrate/20240713140600_create_posts.rb") end it "generates a migration for a gateway" do subject.call(name: "create_posts", gateway: "extra") expect(fs.read("config/db/extra_migrate/20240713140600_create_posts.rb")).to eq migration_file_contents - expect(output).to eq("Created config/db/extra_migrate/20240713140600_create_posts.rb") + expect(output).to eq("\e[32m✓\e[0m \e[32mcreate\e[0m config/db/extra_migrate/20240713140600_create_posts.rb") end it "generates a migration with underscored version of camel cased name" do subject.call(name: "CreatePosts") expect(fs.read("config/db/migrate/20240713140600_create_posts.rb")).to eq migration_file_contents - expect(output).to eq("Created config/db/migrate/20240713140600_create_posts.rb") + expect(output).to eq("\e[32m✓\e[0m \e[32mcreate\e[0m config/db/migrate/20240713140600_create_posts.rb") end it "raises an error if given an invalid name" do @@ -92,7 +92,7 @@ def error_output = err.string.chomp subject.call(name: "create_posts", slice: "main") expect(fs.read("slices/main/config/db/migrate/20240713140600_create_posts.rb")).to eq migration_file_contents - expect(output).to eq("Created slices/main/config/db/migrate/20240713140600_create_posts.rb") + expect(output).to eq("\e[32m✓\e[0m \e[32mcreate\e[0m slices/main/config/db/migrate/20240713140600_create_posts.rb") end context "with existing file" do diff --git a/spec/unit/hanami/cli/commands/app/generate/operation_spec.rb b/spec/unit/hanami/cli/commands/app/generate/operation_spec.rb index 1c229d24..ea7e2a61 100644 --- a/spec/unit/hanami/cli/commands/app/generate/operation_spec.rb +++ b/spec/unit/hanami/cli/commands/app/generate/operation_spec.rb @@ -30,7 +30,7 @@ def call EXPECTED expect(fs.read("app/add_book.rb")).to eq(operation_file) - expect(output).to include("Created app/add_book.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/add_book.rb") expect(output).to include( " Note: We generated a top-level operation. " \ "To generate into a directory, add a namespace: `my_namespace.add_book`" @@ -56,7 +56,7 @@ def call EXPECTED expect(fs.read("app/admin/books/add.rb")).to eq(operation_file) - expect(output).to include("Created app/admin/books/add.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/admin/books/add.rb") end it "generates an operation in a deep namespace with slash separators" do @@ -78,7 +78,7 @@ def call EXPECTED expect(fs.read("app/admin/books/add.rb")).to eq(operation_file) - expect(output).to include("Created app/admin/books/add.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/admin/books/add.rb") end context "with existing file" do @@ -116,7 +116,7 @@ def call EXPECTED expect(fs.read("slices/main/add_book.rb")).to eq(operation_file) - expect(output).to include("Created slices/main/add_book.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/main/add_book.rb") expect(output).to include( " Note: We generated a top-level operation. " \ "To generate into a directory, add a namespace: `my_namespace.add_book`" @@ -143,7 +143,7 @@ def call EXPECTED expect(fs.read("slices/main/admin/books/add.rb")).to eq(operation_file) - expect(output).to include("Created slices/main/admin/books/add.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/main/admin/books/add.rb") end context "with existing file" do diff --git a/spec/unit/hanami/cli/commands/app/generate/part_spec.rb b/spec/unit/hanami/cli/commands/app/generate/part_spec.rb index 44b218f1..a6ca2507 100644 --- a/spec/unit/hanami/cli/commands/app/generate/part_spec.rb +++ b/spec/unit/hanami/cli/commands/app/generate/part_spec.rb @@ -39,7 +39,7 @@ class Part < Hanami::View::Part EXPECTED expect(fs.read("app/views/part.rb")).to eq(base_part) - expect(output).to include("Created app/views/part.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/views/part.rb") # part part = <<~EXPECTED @@ -57,7 +57,7 @@ class User < Test::Views::Part EXPECTED expect(fs.read("app/views/parts/user.rb")).to eq(part) - expect(output).to include("Created app/views/parts/user.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/views/parts/user.rb") end end @@ -116,7 +116,7 @@ class User < Test::Views::Part EXPECTED expect(fs.read("app/views/parts/user.rb")).to eq(part) - expect(output).to include("Created app/views/parts/user.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/views/parts/user.rb") # This is still printed because the fs.write above still prints # expect(output).to_not include("Created app/views/part.rb") @@ -146,7 +146,7 @@ class Part < Hanami::View::Part EXPECTED expect(fs.read("app/views/part.rb")).to eq(app_base_part) - expect(output).to include("Created app/views/part.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/views/part.rb") # base_part base_part = <<~EXPECTED @@ -162,7 +162,7 @@ class Part < Test::Views::Part EXPECTED expect(fs.read("slices/main/views/part.rb")).to eq(base_part) - expect(output).to include("Created slices/main/views/part.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/main/views/part.rb") # part part = <<~EXPECTED @@ -180,7 +180,7 @@ class User < Main::Views::Part EXPECTED expect(fs.read("slices/main/views/parts/user.rb")).to eq(part) - expect(output).to include("Created slices/main/views/parts/user.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/main/views/parts/user.rb") end end end @@ -222,7 +222,7 @@ class User < Main::Views::Part EXPECTED expect(fs.read("slices/main/views/parts/user.rb")).to eq(part) - expect(output).to include("Created slices/main/views/parts/user.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/main/views/parts/user.rb") # This is still printed because the fs.write above still prints # expect(output).to_not include("Created slices/main/views/part.rb") diff --git a/spec/unit/hanami/cli/commands/app/generate/relation_spec.rb b/spec/unit/hanami/cli/commands/app/generate/relation_spec.rb index fd09628b..48c6dfcc 100644 --- a/spec/unit/hanami/cli/commands/app/generate/relation_spec.rb +++ b/spec/unit/hanami/cli/commands/app/generate/relation_spec.rb @@ -46,7 +46,7 @@ class Books < TestApp::DB::Relation RUBY expect(Hanami.app.root.join("app/relations/books.rb").read).to eq relation_file - expect(output).to include("Created app/relations/books.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/relations/books.rb") end it "generates a relation in a namespace with default separator" do @@ -67,7 +67,7 @@ class Drafts < TestApp::DB::Relation RUBY expect(Hanami.app.root.join("app/relations/books/drafts.rb").read).to eq(relation_file) - expect(output).to include("Created app/relations/books/drafts.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/relations/books/drafts.rb") end it "generates an relation in a namespace with slash separators" do @@ -88,7 +88,7 @@ class PublishedBooks < TestApp::DB::Relation RUBY expect(Hanami.app.root.join("app/relations/books/published_books.rb").read).to eq(relation_file) - expect(output).to include("Created app/relations/books/published_books.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/relations/books/published_books.rb") end it "deletes the redundant .keep file" do @@ -114,7 +114,7 @@ class Books < TestApp::DB::Relation RUBY expect(Hanami.app.root.join("app/relations/books.rb").read).to eq relation_file - expect(output).to include("Created app/relations/books.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/relations/books.rb") end context "with existing file" do @@ -152,7 +152,7 @@ class Books < Main::DB::Relation RUBY expect(Hanami.app.root.join("slices/main/relations/books.rb").read).to eq(relation_file) - expect(output).to include("Created slices/main/relations/books.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/main/relations/books.rb") end it "generates a relation in a nested namespace" do @@ -173,7 +173,7 @@ class Drafts < Main::DB::Relation RUBY expect(Hanami.app.root.join("slices/main/relations/book/drafts.rb").read).to eq(relation_file) - expect(output).to include("Created slices/main/relations/book/drafts.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/main/relations/book/drafts.rb") end it "generates a relation for gateway" do @@ -195,7 +195,7 @@ class Drafts < Main::DB::Relation RUBY expect(Hanami.app.root.join("slices/main/relations/book/drafts.rb").read).to eq(relation_file) - expect(output).to include("Created slices/main/relations/book/drafts.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/main/relations/book/drafts.rb") end context "with existing file" do @@ -233,7 +233,7 @@ class Entries < TestApp::DB::Relation RUBY expect(Hanami.app.root.join("app/relations/entries.rb").read).to eq(relation_file) - expect(output).to include("Created app/relations/entries.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/relations/entries.rb") end end end diff --git a/spec/unit/hanami/cli/commands/app/generate/repo_spec.rb b/spec/unit/hanami/cli/commands/app/generate/repo_spec.rb index ffac4e4b..eb5dd2b1 100644 --- a/spec/unit/hanami/cli/commands/app/generate/repo_spec.rb +++ b/spec/unit/hanami/cli/commands/app/generate/repo_spec.rb @@ -31,7 +31,7 @@ class BookRepo < Test::DB::Repo EXPECTED expect(fs.read("app/repos/book_repo.rb")).to eq(repo_file) - expect(output).to include("Created app/repos/book_repo.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/repos/book_repo.rb") end it "passed through repo name if repo_ suffix is preent" do @@ -49,7 +49,7 @@ class BooksRepo < Test::DB::Repo EXPECTED expect(fs.read("app/repos/books_repo.rb")).to eq(repo_file) - expect(output).to include("Created app/repos/books_repo.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/repos/books_repo.rb") end end @@ -70,7 +70,7 @@ class DraftsRepo < Test::DB::Repo EXPECTED expect(fs.read("app/repos/books/drafts_repo.rb")).to eq(repo_file) - expect(output).to include("Created app/repos/books/drafts_repo.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/repos/books/drafts_repo.rb") end it "generates an repo in a deep namespace with slash separators" do @@ -92,7 +92,7 @@ class HardcoverRepo < Test::DB::Repo EXPECTED expect(fs.read("app/repos/books/published/hardcover_repo.rb")).to eq(repo_file) - expect(output).to include("Created app/repos/books/published/hardcover_repo.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/repos/books/published/hardcover_repo.rb") end context "with existing file" do @@ -130,7 +130,7 @@ class BookRepo < Main::DB::Repo EXPECTED expect(fs.read("slices/main/repos/book_repo.rb")).to eq(repo_file) - expect(output).to include("Created slices/main/repos/book_repo.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/main/repos/book_repo.rb") end it "generates a repo in a nested namespace" do @@ -151,7 +151,7 @@ class DraftRepo < Main::DB::Repo EXPECTED expect(fs.read("slices/main/repos/book/draft_repo.rb")).to eq(repo_file) - expect(output).to include("Created slices/main/repos/book/draft_repo.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/main/repos/book/draft_repo.rb") end context "with existing file" do diff --git a/spec/unit/hanami/cli/commands/app/generate/slice_spec.rb b/spec/unit/hanami/cli/commands/app/generate/slice_spec.rb index 79e87bae..8da1f7ae 100644 --- a/spec/unit/hanami/cli/commands/app/generate/slice_spec.rb +++ b/spec/unit/hanami/cli/commands/app/generate/slice_spec.rb @@ -47,11 +47,11 @@ class Routes < Hanami::Routes CODE expect(fs.read("config/routes.rb")).to include(routes) - expect(output).to include("Created config/routes.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m config/routes.rb") # Slice directory expect(fs.directory?("slices/#{slice}")).to be(true) - expect(output).to include("Created slices/#{slice}/") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/#{slice}/") # Action action = <<~CODE @@ -65,9 +65,9 @@ class Action < #{app}::Action CODE expect(fs.read("slices/#{slice}/action.rb")).to eq(action) - expect(output).to include("Created slices/#{slice}/action.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/#{slice}/action.rb") expect(fs.read("slices/#{slice}/actions/.keep")).to eq("") - expect(output).to include("Created slices/#{slice}/actions/.keep") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/#{slice}/actions/.keep") # Relation relation = <<~EXPECTED @@ -81,9 +81,9 @@ class Relation < Test::DB::Relation end EXPECTED expect(fs.read("slices/admin/db/relation.rb")).to eq(relation) - expect(output).to include("Created slices/admin/db/relation.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/admin/db/relation.rb") expect(fs.read("slices/admin/relations/.keep")).to eq("") - expect(output).to include("Created slices/admin/relations/.keep") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/admin/relations/.keep") # Repo repo = <<~EXPECTED @@ -97,9 +97,9 @@ class Repo < Test::DB::Repo end EXPECTED expect(fs.read("slices/admin/db/repo.rb")).to eq(repo) - expect(output).to include("Created slices/admin/db/repo.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/admin/db/repo.rb") expect(fs.read("slices/admin/repos/.keep")).to eq("") - expect(output).to include("Created slices/admin/repos/.keep") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/admin/repos/.keep") # Struct struct = <<~EXPECTED @@ -113,9 +113,9 @@ class Struct < Test::DB::Struct end EXPECTED expect(fs.read("slices/admin/db/struct.rb")).to eq(struct) - expect(output).to include("Created slices/admin/db/struct.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/admin/db/struct.rb") expect(fs.read("slices/admin/structs/.keep")).to eq("") - expect(output).to include("Created slices/admin/structs/.keep") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/admin/structs/.keep") view = <<~RUBY # auto_register: false @@ -127,7 +127,7 @@ class View < Test::View end RUBY expect(fs.read("slices/#{slice}/view.rb")).to eq(view) - expect(output).to include("Created slices/#{slice}/view.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/#{slice}/view.rb") helpers = <<~RUBY # auto_register: false @@ -142,7 +142,7 @@ module Helpers end RUBY expect(fs.read("slices/#{slice}/views/helpers.rb")).to eq(helpers) - expect(output).to include("Created slices/#{slice}/views/helpers.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/#{slice}/views/helpers.rb") operation = <<~RUBY # auto_register: false @@ -154,7 +154,7 @@ class Operation < Test::Operation end RUBY expect(fs.read("slices/#{slice}/operation.rb")).to eq(operation) - expect(output).to include("Created slices/#{slice}/operation.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/#{slice}/operation.rb") layout = <<~ERB @@ -173,14 +173,14 @@ class Operation < Test::Operation ERB expect(fs.read("slices/#{slice}/templates/layouts/app.html.erb")).to eq(layout) - expect(output).to include("Created slices/#{slice}/templates/layouts/app.html.erb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/#{slice}/templates/layouts/app.html.erb") # slices/admin/assets/js/app.js app_js = <<~EXPECTED import "../css/app.css"; EXPECTED expect(fs.read("slices/#{slice}/assets/js/app.js")).to eq(app_js) - expect(output).to include("Created slices/#{slice}/assets/js/app.js") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/#{slice}/assets/js/app.js") # slices/admin/assets/css/app.css app_css = <<~EXPECTED @@ -191,7 +191,7 @@ class Operation < Test::Operation } EXPECTED expect(fs.read("slices/#{slice}/assets/css/app.css")).to eq(app_css) - expect(output).to include("Created slices/#{slice}/assets/css/app.css") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/#{slice}/assets/css/app.css") # slices/admin/assets/images/favicon.ico expect(fs.exist?("slices/#{slice}/assets/images/favicon.ico")).to be(true) @@ -228,7 +228,7 @@ class Operation < Test::Operation it "generates multiple slices over time" do within_application_directory do subject.call(name: "admin") - expect(output).to include("Created config/routes.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m config/routes.rb") subject.call(name: "billing") @@ -252,7 +252,7 @@ class Routes < Hanami::Routes CODE expect(fs.read("config/routes.rb")).to eq(routes) - expect(output).to include("Updated config/routes.rb") + expect(output).to include(" \e[36m↻\e[0m \e[36mupdate\e[0m config/routes.rb") end end diff --git a/spec/unit/hanami/cli/commands/app/generate/struct_spec.rb b/spec/unit/hanami/cli/commands/app/generate/struct_spec.rb index a7cbf72a..3833dfd3 100644 --- a/spec/unit/hanami/cli/commands/app/generate/struct_spec.rb +++ b/spec/unit/hanami/cli/commands/app/generate/struct_spec.rb @@ -28,7 +28,7 @@ class Book < Test::DB::Struct EXPECTED expect(fs.read("app/structs/book.rb")).to eq(struct_file) - expect(output).to include("Created app/structs/book.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/structs/book.rb") end it "generates a struct in a namespace with default separator" do @@ -48,7 +48,7 @@ class BookDraft < Test::DB::Struct EXPECTED expect(fs.read("app/structs/book/book_draft.rb")).to eq(struct_file) - expect(output).to include("Created app/structs/book/book_draft.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/structs/book/book_draft.rb") end it "generates an struct in a deep namespace with slash separators" do @@ -70,7 +70,7 @@ class Hardcover < Test::DB::Struct EXPECTED expect(fs.read("app/structs/book/published/hardcover.rb")).to eq(struct_file) - expect(output).to include("Created app/structs/book/published/hardcover.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/structs/book/published/hardcover.rb") end context "with existing file" do @@ -108,7 +108,7 @@ class Book < Main::DB::Struct EXPECTED expect(fs.read("slices/main/structs/book.rb")).to eq(struct_file) - expect(output).to include("Created slices/main/structs/book.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/main/structs/book.rb") end it "generates a struct in a nested namespace" do @@ -129,7 +129,7 @@ class DraftBook < Main::DB::Struct EXPECTED expect(fs.read("slices/main/structs/book/draft_book.rb")).to eq(struct_file) - expect(output).to include("Created slices/main/structs/book/draft_book.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/main/structs/book/draft_book.rb") end context "with existing file" do diff --git a/spec/unit/hanami/cli/commands/app/generate/view_spec.rb b/spec/unit/hanami/cli/commands/app/generate/view_spec.rb index 50591123..514efb0e 100644 --- a/spec/unit/hanami/cli/commands/app/generate/view_spec.rb +++ b/spec/unit/hanami/cli/commands/app/generate/view_spec.rb @@ -45,7 +45,7 @@ class Index < Test::View EXPECTED expect(fs.read("app/views/users/index.rb")).to eq(view_file) - expect(output).to include("Created app/views/users/index.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/views/users/index.rb") # template expect(fs.directory?("app/templates/users")).to be(true) @@ -55,7 +55,7 @@ class Index < Test::View EXPECTED expect(fs.read("app/templates/users/index.html.erb")).to eq(template_file) - expect(output).to include("Created app/templates/users/index.html.erb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/templates/users/index.html.erb") end end @@ -80,7 +80,7 @@ class Index < Test::View EXPECTED expect(fs.read("app/views/special/users/index.rb")).to eq(view_file) - expect(output).to include("Created app/views/special/users/index.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/views/special/users/index.rb") # template expect(fs.directory?("app/templates/special/users")).to be(true) @@ -90,7 +90,7 @@ class Index < Test::View EXPECTED expect(fs.read("app/templates/special/users/index.html.erb")).to eq(template_file) - expect(output).to include("Created app/templates/special/users/index.html.erb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/templates/special/users/index.html.erb") end end @@ -156,7 +156,7 @@ class Index < Main::View EXPECTED expect(fs.read("slices/main/views/users/index.rb")).to eq(view_file) - expect(output).to include("Created slices/main/views/users/index.rb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/main/views/users/index.rb") # template expect(fs.directory?("slices/main/templates/users")).to be(true) @@ -166,7 +166,7 @@ class Index < Main::View EXPECTED expect(fs.read("slices/main/templates/users/index.html.erb")).to eq(template_file) - expect(output).to include("Created slices/main/templates/users/index.html.erb") + expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/main/templates/users/index.html.erb") end end From 5acc0883ad8472d41bebb1a20d23c21d08ff1a76 Mon Sep 17 00:00:00 2001 From: Andrea Fomera Date: Thu, 23 Oct 2025 21:12:45 -0600 Subject: [PATCH 5/5] Refactor to be more flexible for tty or stdout situations --- lib/hanami/cli/commands/gem/new.rb | 32 ++--- lib/hanami/cli/files.rb | 8 +- lib/hanami/cli/formatter.rb | 62 ++++---- .../cli/commands/app/generate/action_spec.rb | 116 +++++++-------- .../commands/app/generate/component_spec.rb | 18 +-- .../commands/app/generate/migration_spec.rb | 8 +- .../commands/app/generate/operation_spec.rb | 10 +- .../cli/commands/app/generate/part_spec.rb | 14 +- .../commands/app/generate/relation_spec.rb | 16 +-- .../cli/commands/app/generate/repo_spec.rb | 12 +- .../cli/commands/app/generate/slice_spec.rb | 36 ++--- .../cli/commands/app/generate/struct_spec.rb | 10 +- .../cli/commands/app/generate/view_spec.rb | 12 +- spec/unit/hanami/cli/commands/gem/new_spec.rb | 132 +++++++++--------- 14 files changed, 248 insertions(+), 238 deletions(-) diff --git a/lib/hanami/cli/commands/gem/new.rb b/lib/hanami/cli/commands/gem/new.rb index 04b1c910..07e26460 100644 --- a/lib/hanami/cli/commands/gem/new.rb +++ b/lib/hanami/cli/commands/gem/new.rb @@ -158,43 +158,43 @@ def call( skip_view: skip_view, database: normalized_database ) - out.puts Formatter.header("Setting up #{app}...") + out.puts Formatter.header("Setting up #{app}...", out: out) generator.call(app, context: context) do if skip_install out.puts "" - out.puts Formatter.info("Skipping installation") - out.puts Formatter.dim(" To complete setup, run: cd #{app} && bundle exec hanami install") + out.puts Formatter.info("Skipping installation", out: out) + out.puts Formatter.dim(" To complete setup, run: cd #{app} && bundle exec hanami install", out: out) else out.puts "" - out.puts Formatter.info("Installing dependencies...") + out.puts Formatter.info("Installing dependencies...", out: out) bundler.install! unless skip_assets - out.puts Formatter.info("Installing npm packages...") + out.puts Formatter.info("Installing npm packages...", out: out) system_call.call("npm", ["install"]).tap do |result| unless result.successful? - out.puts Formatter.error("NPM installation failed:") - out.puts(result.err.lines.map { |line| Formatter.dim(" #{line}") }) + out.puts Formatter.error("NPM installation failed:", out: out) + out.puts(result.err.lines.map { |line| Formatter.dim(" #{line}", out: out) }) end end end - out.puts Formatter.info("Running hanami install...") + out.puts Formatter.info("Running hanami install...", out: out) run_install_command!(head: head) - out.puts Formatter.info("Running bundle binstubs hanami-cli rake...") + out.puts Formatter.info("Running bundle binstubs hanami-cli rake...", out: out) install_binstubs! - out.puts Formatter.info("Initializing git repository...") + out.puts Formatter.info("Initializing git repository...", out: out) init_git_repository out.puts "" - out.puts Formatter.success("Successfully created #{app}!") + out.puts Formatter.success("Successfully created #{app}!", out: out) out.puts "" - out.puts Formatter.dim("Next steps:") - out.puts Formatter.dim(" cd #{app}") - out.puts Formatter.dim(" bundle exec hanami dev") + out.puts Formatter.dim("Next steps:", out: out) + out.puts Formatter.dim(" cd #{app}", out: out) + out.puts Formatter.dim(" bundle exec hanami dev", out: out) end end end @@ -240,8 +240,8 @@ def install_binstubs! def init_git_repository system_call.call("git", ["init"]).tap do |result| unless result.successful? - out.puts Formatter.warning("Failed to initialize git repository") - out.puts(result.err.lines.map { |line| Formatter.dim(" #{line}") }) + out.puts Formatter.warning("Failed to initialize git repository", out: out) + out.puts(result.err.lines.map { |line| Formatter.dim(" #{line}", out: out) }) end end end diff --git a/lib/hanami/cli/files.rb b/lib/hanami/cli/files.rb index c842d4c0..11927f86 100644 --- a/lib/hanami/cli/files.rb +++ b/lib/hanami/cli/files.rb @@ -84,19 +84,19 @@ def delete_keepfiles(path) end def updated(path) - out.puts Formatter.updated(path) + out.puts Formatter.updated(path, out: out) end def created(path) - out.puts Formatter.created(path) + out.puts Formatter.created(path, out: out) end def created_directory(path) - out.puts Formatter.created_directory(path) + out.puts Formatter.created_directory(path, out: out) end def within_folder(path) - out.puts Formatter.dim("-> Entering `#{path}/` directory...") + out.puts Formatter.dim("-> Entering `#{path}/` directory...", out: out) end def dir_path(path) diff --git a/lib/hanami/cli/formatter.rb b/lib/hanami/cli/formatter.rb index 15e75d9b..e093c286 100644 --- a/lib/hanami/cli/formatter.rb +++ b/lib/hanami/cli/formatter.rb @@ -37,11 +37,12 @@ module Formatter # # @param text [String] the text to colorize # @param color [Symbol] the color name from COLORS + # @param out [IO] the output stream to check for TTY (defaults to $stdout) # @return [String] colorized text # # @api private - def colorize(text, color) - return text unless $stdout.tty? + def colorize(text, color, out: $stdout) + return text unless out.tty? "#{COLORS[color]}#{text}#{COLORS[:reset]}" end @@ -49,103 +50,112 @@ def colorize(text, color) # Formats a create message # # @param path [String] the path that was created + # @param out [IO] the output stream to check for TTY (defaults to $stdout) # @return [String] formatted message # # @api private - def created(path) - icon = colorize(ICONS[:create], :green) - label = colorize("create", :green) + def created(path, out: $stdout) + icon = colorize(ICONS[:create], :green, out: out) + label = colorize("create", :green, out: out) " #{icon} #{label} #{path}" end # Formats a create directory message # # @param path [String] the directory path that was created + # @param out [IO] the output stream to check for TTY (defaults to $stdout) # @return [String] formatted message # # @api private - def created_directory(path) - icon = colorize(ICONS[:create], :green) - label = colorize("create directory", :green) + def created_directory(path, out: $stdout) + icon = colorize(ICONS[:create], :green, out: out) + label = colorize("create directory", :green, out: out) "#{icon} #{label} #{path}" end # Formats an update message # # @param path [String] the path that was updated + # @param out [IO] the output stream to check for TTY (defaults to $stdout) # @return [String] formatted message # # @api private - def updated(path) - icon = colorize(ICONS[:update], :cyan) - label = colorize("update", :cyan) + def updated(path, out: $stdout) + icon = colorize(ICONS[:update], :cyan, out: out) + label = colorize("update", :cyan, out: out) " #{icon} #{label} #{path}" end # Formats an info message # # @param text [String] the message text + # @param out [IO] the output stream to check for TTY (defaults to $stdout) # @return [String] formatted message # # @api private - def info(text) - icon = colorize(ICONS[:info], :blue) + def info(text, out: $stdout) + icon = colorize(ICONS[:info], :blue, out: out) "#{icon} #{text}" end # Formats a success message # # @param text [String] the message text + # @param out [IO] the output stream to check for TTY (defaults to $stdout) # @return [String] formatted message # # @api private - def success(text) - icon = colorize(ICONS[:success], :green) - label = colorize("✓", :green) - "#{label} #{colorize(text, :green)}" + def success(text, out: $stdout) + icon = colorize(ICONS[:success], :green, out: out) + label = colorize("✓", :green, out: out) + "#{label} #{colorize(text, :green, out: out)}" end # Formats a warning message # # @param text [String] the message text + # @param out [IO] the output stream to check for TTY (defaults to $stdout) # @return [String] formatted message # # @api private - def warning(text) - icon = colorize(ICONS[:warning], :yellow) - label = colorize("warning", :yellow) + def warning(text, out: $stdout) + icon = colorize(ICONS[:warning], :yellow, out: out) + label = colorize("warning", :yellow, out: out) "#{icon} #{label} #{text}" end # Formats an error message # # @param text [String] the message text + # @param out [IO] the output stream to check for TTY (defaults to $stdout) # @return [String] formatted message # # @api private - def error(text) - icon = colorize(ICONS[:error], :red) - label = colorize("error", :red) + def error(text, out: $stdout) + icon = colorize(ICONS[:error], :red, out: out) + label = colorize("error", :red, out: out) "#{icon} #{label} #{text}" end # Formats a section header # # @param text [String] the header text + # @param out [IO] the output stream to check for TTY (defaults to $stdout) # @return [String] formatted header # # @api private - def header(text) - "\n#{colorize(text, :bold)}" + def header(text, out: $stdout) + "\n#{colorize(text, :bold, out: out)}" end # Formats a dim/secondary text # # @param text [String] the text to dim + # @param out [IO] the output stream to check for TTY (defaults to $stdout) # @return [String] formatted text # # @api private - def dim(text) + def dim(text, out: $stdout) text # No special dim color, just return plain text for now end end diff --git a/spec/unit/hanami/cli/commands/app/generate/action_spec.rb b/spec/unit/hanami/cli/commands/app/generate/action_spec.rb index 7e828ac6..500558ae 100644 --- a/spec/unit/hanami/cli/commands/app/generate/action_spec.rb +++ b/spec/unit/hanami/cli/commands/app/generate/action_spec.rb @@ -33,10 +33,10 @@ def error_output = err.string.chomp within_application_directory do generate_action - expect(output).to include(" \e[36m↻\e[0m \e[36mupdate\e[0m config/routes.rb") - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/actions/#{controller}/#{action}.rb") - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/views/#{controller}/#{action}.rb") - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/templates/#{controller}/#{action}.html.erb") + expect(output).to include(" ↻ update config/routes.rb") + expect(output).to include(" ✓ create app/actions/#{controller}/#{action}.rb") + expect(output).to include(" ✓ create app/views/#{controller}/#{action}.rb") + expect(output).to include(" ✓ create app/templates/#{controller}/#{action}.html.erb") end end end @@ -122,7 +122,7 @@ class Routes < Hanami::Routes # route expect(fs.read("config/routes.rb")).to eq(routes) - expect(output).to include(" \e[36m↻\e[0m \e[36mupdate\e[0m config/routes.rb") + expect(output).to include(" ↻ update config/routes.rb") # action action_file = <<~EXPECTED @@ -142,7 +142,7 @@ def handle(request, response) EXPECTED expect(fs.read("app/actions/#{controller}/#{action}.rb")).to eq(action_file) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/actions/#{controller}/#{action}.rb") + expect(output).to include(" ✓ create app/actions/#{controller}/#{action}.rb") expect(fs.directory?("app/views/#{controller}")).to eq(false) expect(fs.exist?("app/views/#{controller}/#{action}.rb")).to eq(false) @@ -177,31 +177,31 @@ def handle(request, response) within_application_directory do subject.call(name: "users.index") expect(fs.read("config/routes.rb")).to match(%(get "/users", to: "users.index")) - expect(output).to include(" \e[36m↻\e[0m \e[36mupdate\e[0m config/routes.rb") + expect(output).to include(" ↻ update config/routes.rb") subject.call(name: "users.new") expect(fs.read("config/routes.rb")).to match(%(get "/users/new", to: "users.new")) - expect(output).to include(" \e[36m↻\e[0m \e[36mupdate\e[0m config/routes.rb") + expect(output).to include(" ↻ update config/routes.rb") subject.call(name: "users.create") expect(fs.read("config/routes.rb")).to match(%(post "/users", to: "users.create")) - expect(output).to include(" \e[36m↻\e[0m \e[36mupdate\e[0m config/routes.rb") + expect(output).to include(" ↻ update config/routes.rb") subject.call(name: "users.edit") expect(fs.read("config/routes.rb")).to match(%(get "/users/:id/edit", to: "users.edit")) - expect(output).to include(" \e[36m↻\e[0m \e[36mupdate\e[0m config/routes.rb") + expect(output).to include(" ↻ update config/routes.rb") subject.call(name: "users.update") expect(fs.read("config/routes.rb")).to match(%(patch "/users/:id", to: "users.update")) - expect(output).to include(" \e[36m↻\e[0m \e[36mupdate\e[0m config/routes.rb") + expect(output).to include(" ↻ update config/routes.rb") subject.call(name: "users.show") expect(fs.read("config/routes.rb")).to match(%(get "/users/:id", to: "users.show")) - expect(output).to include(" \e[36m↻\e[0m \e[36mupdate\e[0m config/routes.rb") + expect(output).to include(" ↻ update config/routes.rb") subject.call(name: "users.destroy") expect(fs.read("config/routes.rb")).to match(%(delete "/users/:id", to: "users.destroy")) - expect(output).to include(" \e[36m↻\e[0m \e[36mupdate\e[0m config/routes.rb") + expect(output).to include(" ↻ update config/routes.rb") end end @@ -209,7 +209,7 @@ def handle(request, response) within_application_directory do subject.call(name: "talent.apply", url_path: "/talent/apply") expect(fs.read("config/routes.rb")).to match(%(get "/talent/apply", to: "talent.apply")) - expect(output).to include(" \e[36m↻\e[0m \e[36mupdate\e[0m config/routes.rb") + expect(output).to include(" ↻ update config/routes.rb") end end @@ -217,7 +217,7 @@ def handle(request, response) within_application_directory do subject.call(name: action_name, url_path: "/people") expect(fs.read("config/routes.rb")).to match(%(get "/people", to: "users.index")) - expect(output).to include(" \e[36m↻\e[0m \e[36mupdate\e[0m config/routes.rb") + expect(output).to include(" ↻ update config/routes.rb") end end @@ -225,7 +225,7 @@ def handle(request, response) within_application_directory do subject.call(name: action_name, http_method: "put") expect(fs.read("config/routes.rb")).to match(%(put "/users", to: "users.index")) - expect(output).to include(" \e[36m↻\e[0m \e[36mupdate\e[0m config/routes.rb") + expect(output).to include(" ↻ update config/routes.rb") end end @@ -235,7 +235,7 @@ def handle(request, response) subject.call(name: action_name, skip_view: true) expect(fs.read("config/routes.rb")).to match(%(get "/api/users/thing", to: "api.users.thing")) - expect(output).to include(" \e[36m↻\e[0m \e[36mupdate\e[0m config/routes.rb") + expect(output).to include(" ↻ update config/routes.rb") action_file = <<~EXPECTED # frozen_string_literal: true @@ -256,7 +256,7 @@ def handle(request, response) EXPECTED expect(fs.read("app/actions/api/users/thing.rb")).to eq(action_file) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/actions/api/users/thing.rb") + expect(output).to include(" ✓ create app/actions/api/users/thing.rb") end end @@ -337,7 +337,7 @@ class Routes < Hanami::Routes # route expect(fs.read("config/routes.rb")).to eq(routes) - expect(output).to include(" \e[36m↻\e[0m \e[36mupdate\e[0m config/routes.rb") + expect(output).to include(" ↻ update config/routes.rb") # action action_file = <<~EXPECTED @@ -356,7 +356,7 @@ def handle(request, response) EXPECTED expect(fs.read("app/actions/#{controller}/#{action}.rb")).to eq(action_file) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/actions/#{controller}/#{action}.rb") + expect(output).to include(" ✓ create app/actions/#{controller}/#{action}.rb") # view view_file = <<~EXPECTED @@ -373,7 +373,7 @@ class #{inflector.camelize(action)} < #{inflector.camelize(app)}::View EXPECTED expect(fs.read("app/views/#{controller}/#{action}.rb")).to eq(view_file) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/views/#{controller}/#{action}.rb") + expect(output).to include(" ✓ create app/views/#{controller}/#{action}.rb") # template expect(fs.directory?("app/templates/#{controller}")).to be(true) @@ -383,7 +383,7 @@ class #{inflector.camelize(action)} < #{inflector.camelize(app)}::View EXPECTED expect(fs.read("app/templates/#{controller}/#{action}.html.erb")).to eq(template_file) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/templates/#{controller}/#{action}.html.erb") + expect(output).to include(" ✓ create app/templates/#{controller}/#{action}.html.erb") end end @@ -394,7 +394,7 @@ class #{inflector.camelize(action)} < #{inflector.camelize(app)}::View subject.call(name: action_name) expect(fs.read("config/routes.rb")).to match(%(get "/api/users/thing", to: "api.users.thing")) - expect(output).to include(" \e[36m↻\e[0m \e[36mupdate\e[0m config/routes.rb") + expect(output).to include(" ↻ update config/routes.rb") action_file = <<~EXPECTED # frozen_string_literal: true @@ -414,7 +414,7 @@ def handle(request, response) EXPECTED expect(fs.read("app/actions/api/users/thing.rb")).to eq(action_file) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/actions/api/users/thing.rb") + expect(output).to include(" ✓ create app/actions/api/users/thing.rb") end end end @@ -457,7 +457,7 @@ def handle(request, response) EXPECTED expect(fs.read("app/actions/#{controller}/#{action}.rb")).to eq(action_file) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/actions/#{controller}/#{action}.rb") + expect(output).to include(" ✓ create app/actions/#{controller}/#{action}.rb") # view view_file = <<~EXPECTED @@ -474,7 +474,7 @@ class #{inflector.camelize(action)} < #{inflector.camelize(app)}::View EXPECTED expect(fs.read("app/views/#{controller}/#{action}.rb")).to eq(view_file) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/views/#{controller}/#{action}.rb") + expect(output).to include(" ✓ create app/views/#{controller}/#{action}.rb") # template expect(fs.directory?("app/templates/#{controller}")).to be(true) @@ -484,7 +484,7 @@ class #{inflector.camelize(action)} < #{inflector.camelize(app)}::View EXPECTED expect(fs.read("app/templates/#{controller}/#{action}.html.erb")).to eq(template_file) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/templates/#{controller}/#{action}.html.erb") + expect(output).to include(" ✓ create app/templates/#{controller}/#{action}.html.erb") end end @@ -569,7 +569,7 @@ class Routes < Hanami::Routes # route expect(fs.read("config/routes.rb")).to eq(expected_routes) - expect(output).to include(" \e[36m↻\e[0m \e[36mupdate\e[0m config/routes.rb") + expect(output).to include(" ↻ update config/routes.rb") expected_action = <<~CODE # frozen_string_literal: true @@ -586,7 +586,7 @@ def handle(request, response) end CODE expect(fs.read("app/actions/users/create.rb")).to eq(expected_action) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/actions/users/create.rb") + expect(output).to include(" ✓ create app/actions/users/create.rb") expect(fs.exist?("app/views/users/create.rb")).to be(false) expect(fs.exist?("app/templates/users/create.html.erb")).to be(false) @@ -631,7 +631,7 @@ class Routes < Hanami::Routes # route expect(fs.read("config/routes.rb")).to eq(expected_routes) - expect(output).to include(" \e[36m↻\e[0m \e[36mupdate\e[0m config/routes.rb") + expect(output).to include(" ↻ update config/routes.rb") expected_action = <<~CODE # frozen_string_literal: true @@ -648,7 +648,7 @@ def handle(request, response) end CODE expect(fs.read("app/actions/users/create.rb")).to eq(expected_action) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/actions/users/create.rb") + expect(output).to include(" ✓ create app/actions/users/create.rb") expected_view = <<~CODE # frozen_string_literal: true @@ -663,14 +663,14 @@ class Create < #{app}::View end CODE expect(fs.read("app/views/users/create.rb")).to eq(expected_view) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/views/users/create.rb") + expect(output).to include(" ✓ create app/views/users/create.rb") expected_template = <<~EXPECTED

#{inflector.camelize(app)}::Views::Users::Create

EXPECTED expect(fs.read("app/templates/users/create.html.erb")).to eq(expected_template) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/templates/users/create.html.erb") + expect(output).to include(" ✓ create app/templates/users/create.html.erb") end end @@ -708,7 +708,7 @@ class Routes < Hanami::Routes # route expect(fs.read("config/routes.rb")).to eq(expected_routes) - expect(output).to include(" \e[36m↻\e[0m \e[36mupdate\e[0m config/routes.rb") + expect(output).to include(" ↻ update config/routes.rb") expected_action = <<~CODE # frozen_string_literal: true @@ -726,7 +726,7 @@ def handle(request, response) end CODE expect(fs.read("app/actions/users/create.rb")).to eq(expected_action) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/actions/users/create.rb") + expect(output).to include(" ✓ create app/actions/users/create.rb") expect(fs.exist?("app/views/users/create.rb")).to be(false) expect(fs.exist?("app/templates/users/create.html.erb")).to be(false) @@ -809,7 +809,7 @@ class Routes < Hanami::Routes # route expect(fs.read("config/routes.rb")).to eq(expected_routes) - expect(output).to include(" \e[36m↻\e[0m \e[36mupdate\e[0m config/routes.rb") + expect(output).to include(" ↻ update config/routes.rb") expected_action = <<~CODE # frozen_string_literal: true @@ -826,7 +826,7 @@ def handle(request, response) end CODE expect(fs.read("app/actions/users/update.rb")).to eq(expected_action) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/actions/users/update.rb") + expect(output).to include(" ✓ create app/actions/users/update.rb") expect(fs.exist?("app/views/users/update.rb")).to be(false) expect(fs.exist?("app/templates/users/update.html.erb")).to be(false) @@ -871,7 +871,7 @@ class Routes < Hanami::Routes # route expect(fs.read("config/routes.rb")).to eq(expected_routes) - expect(output).to include(" \e[36m↻\e[0m \e[36mupdate\e[0m config/routes.rb") + expect(output).to include(" ↻ update config/routes.rb") expected_action = <<~CODE # frozen_string_literal: true @@ -888,7 +888,7 @@ def handle(request, response) end CODE expect(fs.read("app/actions/users/update.rb")).to eq(expected_action) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/actions/users/update.rb") + expect(output).to include(" ✓ create app/actions/users/update.rb") expected_view = <<~CODE # frozen_string_literal: true @@ -903,14 +903,14 @@ class Update < #{app}::View end CODE expect(fs.read("app/views/users/update.rb")).to eq(expected_view) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/views/users/update.rb") + expect(output).to include(" ✓ create app/views/users/update.rb") expected_template = <<~EXPECTED

#{inflector.camelize(app)}::Views::Users::Update

EXPECTED expect(fs.read("app/templates/users/update.html.erb")).to eq(expected_template) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/templates/users/update.html.erb") + expect(output).to include(" ✓ create app/templates/users/update.html.erb") end end @@ -948,7 +948,7 @@ class Routes < Hanami::Routes # route expect(fs.read("config/routes.rb")).to eq(expected_routes) - expect(output).to include(" \e[36m↻\e[0m \e[36mupdate\e[0m config/routes.rb") + expect(output).to include(" ↻ update config/routes.rb") expected_action = <<~CODE # frozen_string_literal: true @@ -966,7 +966,7 @@ def handle(request, response) end CODE expect(fs.read("app/actions/users/update.rb")).to eq(expected_action) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/actions/users/update.rb") + expect(output).to include(" ✓ create app/actions/users/update.rb") expect(fs.exist?("app/views/users/update.rb")).to be(false) expect(fs.exist?("app/templates/users/update.html.erb")).to be(false) @@ -1015,12 +1015,12 @@ class Routes < Hanami::Routes # route expect(fs.read("config/routes.rb")).to eq(routes) - expect(output).to include(" \e[36m↻\e[0m \e[36mupdate\e[0m config/routes.rb") - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/#{slice}/actions/#{controller}/") + expect(output).to include(" ↻ update config/routes.rb") + expect(output).to include(" ✓ create slices/#{slice}/actions/#{controller}/") # action expect(fs.directory?("slices/#{slice}/actions/#{controller}")).to be(true) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/#{slice}/actions/#{controller}/") + expect(output).to include(" ✓ create slices/#{slice}/actions/#{controller}/") action_file = <<~EXPECTED # frozen_string_literal: true @@ -1038,7 +1038,7 @@ def handle(request, response) end EXPECTED expect(fs.read("slices/#{slice}/actions/#{controller}/#{action}.rb")).to eq(action_file) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/#{slice}/actions/#{controller}/#{action}.rb") + expect(output).to include(" ✓ create slices/#{slice}/actions/#{controller}/#{action}.rb") # view expect(fs.directory?("slices/#{slice}/views/#{controller}")).to be(false) @@ -1225,12 +1225,12 @@ class Routes < Hanami::Routes # route expect(fs.read("config/routes.rb")).to eq(routes) - expect(output).to include(" \e[36m↻\e[0m \e[36mupdate\e[0m config/routes.rb") - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/#{slice}/actions/#{controller}/") + expect(output).to include(" ↻ update config/routes.rb") + expect(output).to include(" ✓ create slices/#{slice}/actions/#{controller}/") # action expect(fs.directory?("slices/#{slice}/actions/#{controller}")).to be(true) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/#{slice}/actions/#{controller}/") + expect(output).to include(" ✓ create slices/#{slice}/actions/#{controller}/") action_file = <<~EXPECTED # frozen_string_literal: true @@ -1247,11 +1247,11 @@ def handle(request, response) end EXPECTED expect(fs.read("slices/#{slice}/actions/#{controller}/#{action}.rb")).to eq(action_file) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/#{slice}/actions/#{controller}/#{action}.rb") + expect(output).to include(" ✓ create slices/#{slice}/actions/#{controller}/#{action}.rb") # view expect(fs.directory?("slices/#{slice}/views/#{controller}")).to be(true) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/#{slice}/views/#{controller}/") + expect(output).to include(" ✓ create slices/#{slice}/views/#{controller}/") view_file = <<~EXPECTED # frozen_string_literal: true @@ -1266,17 +1266,17 @@ class #{inflector.camelize(action)} < #{inflector.camelize(slice)}::View end EXPECTED expect(fs.read("slices/#{slice}/views/#{controller}/#{action}.rb")).to eq(view_file) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/#{slice}/views/#{controller}/#{action}.rb") + expect(output).to include(" ✓ create slices/#{slice}/views/#{controller}/#{action}.rb") # template expect(fs.directory?("slices/#{slice}/templates/#{controller}")).to be(true) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/#{slice}/templates/#{controller}/") + expect(output).to include(" ✓ create slices/#{slice}/templates/#{controller}/") template_file = <<~EXPECTED

#{inflector.camelize(slice)}::Views::#{inflector.camelize(controller)}::#{inflector.camelize(action)}

EXPECTED expect(fs.read("slices/#{slice}/templates/#{controller}/#{action}.html.erb")).to eq(template_file) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/#{slice}/templates/#{controller}/#{action}.html.erb") + expect(output).to include(" ✓ create slices/#{slice}/templates/#{controller}/#{action}.html.erb") end end @@ -1356,8 +1356,8 @@ class Routes < Hanami::Routes # route expect(fs.read("config/routes.rb")).to eq(expected_routes) - expect(output).to include(" \e[36m↻\e[0m \e[36mupdate\e[0m config/routes.rb") - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/#{slice}/actions/#{controller}/") + expect(output).to include(" ↻ update config/routes.rb") + expect(output).to include(" ✓ create slices/#{slice}/actions/#{controller}/") # action expected_action = <<~EXPECTED @@ -1375,7 +1375,7 @@ def handle(request, response) end EXPECTED expect(fs.read("slices/#{slice}/actions/#{controller}/#{action}.rb")).to eq(expected_action) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/#{slice}/actions/#{controller}/#{action}.rb") + expect(output).to include(" ✓ create slices/#{slice}/actions/#{controller}/#{action}.rb") # view expect(output).to_not include("Created slices/#{slice}/views/#{controller}/#{action}.rb") diff --git a/spec/unit/hanami/cli/commands/app/generate/component_spec.rb b/spec/unit/hanami/cli/commands/app/generate/component_spec.rb index 3535cd8a..b7449be6 100644 --- a/spec/unit/hanami/cli/commands/app/generate/component_spec.rb +++ b/spec/unit/hanami/cli/commands/app/generate/component_spec.rb @@ -38,7 +38,7 @@ class SendWelcomeEmail EXPECTED expect(fs.read("app/operations/send_welcome_email.rb")).to eq(component) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/operations/send_welcome_email.rb") + expect(output).to include(" ✓ create app/operations/send_welcome_email.rb") end context "with existing file" do @@ -79,7 +79,7 @@ class SendWelcomeEmail EXPECTED expect(fs.read("app/operations/user/mailing/send_welcome_email.rb")).to eq(component) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/operations/user/mailing/send_welcome_email.rb") + expect(output).to include(" ✓ create app/operations/user/mailing/send_welcome_email.rb") end context "with existing file" do @@ -119,7 +119,7 @@ class WelcomeEmail EXPECTED expect(fs.read("slices/main/renderers/welcome_email.rb")).to eq(component) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/main/renderers/welcome_email.rb") + expect(output).to include(" ✓ create slices/main/renderers/welcome_email.rb") end context "with existing file" do @@ -161,7 +161,7 @@ class WelcomeEmail EXPECTED expect(fs.read("slices/main/renderers/user/mailing/welcome_email.rb")).to eq(component) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/main/renderers/user/mailing/welcome_email.rb") + expect(output).to include(" ✓ create slices/main/renderers/user/mailing/welcome_email.rb") end context "with existing file" do @@ -205,7 +205,7 @@ class SendWelcomeEmail EXPECTED expect(fs.read("app/operations/send_welcome_email.rb")).to eq(component) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/operations/send_welcome_email.rb") + expect(output).to include(" ✓ create app/operations/send_welcome_email.rb") end end @@ -223,7 +223,7 @@ class CreateEntry EXPECTED expect(fs.read("app/create_entry.rb")).to eq(component) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/create_entry.rb") + expect(output).to include(" ✓ create app/create_entry.rb") end context "when nested" do @@ -242,7 +242,7 @@ class CreateEntry EXPECTED expect(fs.read("app/services/create_entry.rb")).to eq(component) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/services/create_entry.rb") + expect(output).to include(" ✓ create app/services/create_entry.rb") end end @@ -262,7 +262,7 @@ class CreateEntry EXPECTED expect(fs.read("app/services/create_entry.rb")).to eq(component) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/services/create_entry.rb") + expect(output).to include(" ✓ create app/services/create_entry.rb") end end @@ -282,7 +282,7 @@ class CreateEntry EXPECTED expect(fs.read("app/services/create_entry.rb")).to eq(component) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/services/create_entry.rb") + expect(output).to include(" ✓ create app/services/create_entry.rb") end end end diff --git a/spec/unit/hanami/cli/commands/app/generate/migration_spec.rb b/spec/unit/hanami/cli/commands/app/generate/migration_spec.rb index 1ad381c8..3fafb9a8 100644 --- a/spec/unit/hanami/cli/commands/app/generate/migration_spec.rb +++ b/spec/unit/hanami/cli/commands/app/generate/migration_spec.rb @@ -40,21 +40,21 @@ def error_output = err.string.chomp subject.call(name: "create_posts") expect(fs.read("config/db/migrate/20240713140600_create_posts.rb")).to eq migration_file_contents - expect(output).to eq("\e[32m✓\e[0m \e[32mcreate\e[0m config/db/migrate/20240713140600_create_posts.rb") + expect(output).to eq("✓ create config/db/migrate/20240713140600_create_posts.rb") end it "generates a migration for a gateway" do subject.call(name: "create_posts", gateway: "extra") expect(fs.read("config/db/extra_migrate/20240713140600_create_posts.rb")).to eq migration_file_contents - expect(output).to eq("\e[32m✓\e[0m \e[32mcreate\e[0m config/db/extra_migrate/20240713140600_create_posts.rb") + expect(output).to eq("✓ create config/db/extra_migrate/20240713140600_create_posts.rb") end it "generates a migration with underscored version of camel cased name" do subject.call(name: "CreatePosts") expect(fs.read("config/db/migrate/20240713140600_create_posts.rb")).to eq migration_file_contents - expect(output).to eq("\e[32m✓\e[0m \e[32mcreate\e[0m config/db/migrate/20240713140600_create_posts.rb") + expect(output).to eq("✓ create config/db/migrate/20240713140600_create_posts.rb") end it "raises an error if given an invalid name" do @@ -92,7 +92,7 @@ def error_output = err.string.chomp subject.call(name: "create_posts", slice: "main") expect(fs.read("slices/main/config/db/migrate/20240713140600_create_posts.rb")).to eq migration_file_contents - expect(output).to eq("\e[32m✓\e[0m \e[32mcreate\e[0m slices/main/config/db/migrate/20240713140600_create_posts.rb") + expect(output).to eq("✓ create slices/main/config/db/migrate/20240713140600_create_posts.rb") end context "with existing file" do diff --git a/spec/unit/hanami/cli/commands/app/generate/operation_spec.rb b/spec/unit/hanami/cli/commands/app/generate/operation_spec.rb index ea7e2a61..cc0fb8d8 100644 --- a/spec/unit/hanami/cli/commands/app/generate/operation_spec.rb +++ b/spec/unit/hanami/cli/commands/app/generate/operation_spec.rb @@ -30,7 +30,7 @@ def call EXPECTED expect(fs.read("app/add_book.rb")).to eq(operation_file) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/add_book.rb") + expect(output).to include(" ✓ create app/add_book.rb") expect(output).to include( " Note: We generated a top-level operation. " \ "To generate into a directory, add a namespace: `my_namespace.add_book`" @@ -56,7 +56,7 @@ def call EXPECTED expect(fs.read("app/admin/books/add.rb")).to eq(operation_file) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/admin/books/add.rb") + expect(output).to include(" ✓ create app/admin/books/add.rb") end it "generates an operation in a deep namespace with slash separators" do @@ -78,7 +78,7 @@ def call EXPECTED expect(fs.read("app/admin/books/add.rb")).to eq(operation_file) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/admin/books/add.rb") + expect(output).to include(" ✓ create app/admin/books/add.rb") end context "with existing file" do @@ -116,7 +116,7 @@ def call EXPECTED expect(fs.read("slices/main/add_book.rb")).to eq(operation_file) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/main/add_book.rb") + expect(output).to include(" ✓ create slices/main/add_book.rb") expect(output).to include( " Note: We generated a top-level operation. " \ "To generate into a directory, add a namespace: `my_namespace.add_book`" @@ -143,7 +143,7 @@ def call EXPECTED expect(fs.read("slices/main/admin/books/add.rb")).to eq(operation_file) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/main/admin/books/add.rb") + expect(output).to include(" ✓ create slices/main/admin/books/add.rb") end context "with existing file" do diff --git a/spec/unit/hanami/cli/commands/app/generate/part_spec.rb b/spec/unit/hanami/cli/commands/app/generate/part_spec.rb index a6ca2507..fa8b7dce 100644 --- a/spec/unit/hanami/cli/commands/app/generate/part_spec.rb +++ b/spec/unit/hanami/cli/commands/app/generate/part_spec.rb @@ -39,7 +39,7 @@ class Part < Hanami::View::Part EXPECTED expect(fs.read("app/views/part.rb")).to eq(base_part) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/views/part.rb") + expect(output).to include(" ✓ create app/views/part.rb") # part part = <<~EXPECTED @@ -57,7 +57,7 @@ class User < Test::Views::Part EXPECTED expect(fs.read("app/views/parts/user.rb")).to eq(part) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/views/parts/user.rb") + expect(output).to include(" ✓ create app/views/parts/user.rb") end end @@ -116,7 +116,7 @@ class User < Test::Views::Part EXPECTED expect(fs.read("app/views/parts/user.rb")).to eq(part) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/views/parts/user.rb") + expect(output).to include(" ✓ create app/views/parts/user.rb") # This is still printed because the fs.write above still prints # expect(output).to_not include("Created app/views/part.rb") @@ -146,7 +146,7 @@ class Part < Hanami::View::Part EXPECTED expect(fs.read("app/views/part.rb")).to eq(app_base_part) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/views/part.rb") + expect(output).to include(" ✓ create app/views/part.rb") # base_part base_part = <<~EXPECTED @@ -162,7 +162,7 @@ class Part < Test::Views::Part EXPECTED expect(fs.read("slices/main/views/part.rb")).to eq(base_part) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/main/views/part.rb") + expect(output).to include(" ✓ create slices/main/views/part.rb") # part part = <<~EXPECTED @@ -180,7 +180,7 @@ class User < Main::Views::Part EXPECTED expect(fs.read("slices/main/views/parts/user.rb")).to eq(part) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/main/views/parts/user.rb") + expect(output).to include(" ✓ create slices/main/views/parts/user.rb") end end end @@ -222,7 +222,7 @@ class User < Main::Views::Part EXPECTED expect(fs.read("slices/main/views/parts/user.rb")).to eq(part) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/main/views/parts/user.rb") + expect(output).to include(" ✓ create slices/main/views/parts/user.rb") # This is still printed because the fs.write above still prints # expect(output).to_not include("Created slices/main/views/part.rb") diff --git a/spec/unit/hanami/cli/commands/app/generate/relation_spec.rb b/spec/unit/hanami/cli/commands/app/generate/relation_spec.rb index 48c6dfcc..9aa0323f 100644 --- a/spec/unit/hanami/cli/commands/app/generate/relation_spec.rb +++ b/spec/unit/hanami/cli/commands/app/generate/relation_spec.rb @@ -46,7 +46,7 @@ class Books < TestApp::DB::Relation RUBY expect(Hanami.app.root.join("app/relations/books.rb").read).to eq relation_file - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/relations/books.rb") + expect(output).to include(" ✓ create app/relations/books.rb") end it "generates a relation in a namespace with default separator" do @@ -67,7 +67,7 @@ class Drafts < TestApp::DB::Relation RUBY expect(Hanami.app.root.join("app/relations/books/drafts.rb").read).to eq(relation_file) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/relations/books/drafts.rb") + expect(output).to include(" ✓ create app/relations/books/drafts.rb") end it "generates an relation in a namespace with slash separators" do @@ -88,7 +88,7 @@ class PublishedBooks < TestApp::DB::Relation RUBY expect(Hanami.app.root.join("app/relations/books/published_books.rb").read).to eq(relation_file) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/relations/books/published_books.rb") + expect(output).to include(" ✓ create app/relations/books/published_books.rb") end it "deletes the redundant .keep file" do @@ -114,7 +114,7 @@ class Books < TestApp::DB::Relation RUBY expect(Hanami.app.root.join("app/relations/books.rb").read).to eq relation_file - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/relations/books.rb") + expect(output).to include(" ✓ create app/relations/books.rb") end context "with existing file" do @@ -152,7 +152,7 @@ class Books < Main::DB::Relation RUBY expect(Hanami.app.root.join("slices/main/relations/books.rb").read).to eq(relation_file) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/main/relations/books.rb") + expect(output).to include(" ✓ create slices/main/relations/books.rb") end it "generates a relation in a nested namespace" do @@ -173,7 +173,7 @@ class Drafts < Main::DB::Relation RUBY expect(Hanami.app.root.join("slices/main/relations/book/drafts.rb").read).to eq(relation_file) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/main/relations/book/drafts.rb") + expect(output).to include(" ✓ create slices/main/relations/book/drafts.rb") end it "generates a relation for gateway" do @@ -195,7 +195,7 @@ class Drafts < Main::DB::Relation RUBY expect(Hanami.app.root.join("slices/main/relations/book/drafts.rb").read).to eq(relation_file) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/main/relations/book/drafts.rb") + expect(output).to include(" ✓ create slices/main/relations/book/drafts.rb") end context "with existing file" do @@ -233,7 +233,7 @@ class Entries < TestApp::DB::Relation RUBY expect(Hanami.app.root.join("app/relations/entries.rb").read).to eq(relation_file) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/relations/entries.rb") + expect(output).to include(" ✓ create app/relations/entries.rb") end end end diff --git a/spec/unit/hanami/cli/commands/app/generate/repo_spec.rb b/spec/unit/hanami/cli/commands/app/generate/repo_spec.rb index eb5dd2b1..3db23d48 100644 --- a/spec/unit/hanami/cli/commands/app/generate/repo_spec.rb +++ b/spec/unit/hanami/cli/commands/app/generate/repo_spec.rb @@ -31,7 +31,7 @@ class BookRepo < Test::DB::Repo EXPECTED expect(fs.read("app/repos/book_repo.rb")).to eq(repo_file) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/repos/book_repo.rb") + expect(output).to include(" ✓ create app/repos/book_repo.rb") end it "passed through repo name if repo_ suffix is preent" do @@ -49,7 +49,7 @@ class BooksRepo < Test::DB::Repo EXPECTED expect(fs.read("app/repos/books_repo.rb")).to eq(repo_file) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/repos/books_repo.rb") + expect(output).to include(" ✓ create app/repos/books_repo.rb") end end @@ -70,7 +70,7 @@ class DraftsRepo < Test::DB::Repo EXPECTED expect(fs.read("app/repos/books/drafts_repo.rb")).to eq(repo_file) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/repos/books/drafts_repo.rb") + expect(output).to include(" ✓ create app/repos/books/drafts_repo.rb") end it "generates an repo in a deep namespace with slash separators" do @@ -92,7 +92,7 @@ class HardcoverRepo < Test::DB::Repo EXPECTED expect(fs.read("app/repos/books/published/hardcover_repo.rb")).to eq(repo_file) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/repos/books/published/hardcover_repo.rb") + expect(output).to include(" ✓ create app/repos/books/published/hardcover_repo.rb") end context "with existing file" do @@ -130,7 +130,7 @@ class BookRepo < Main::DB::Repo EXPECTED expect(fs.read("slices/main/repos/book_repo.rb")).to eq(repo_file) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/main/repos/book_repo.rb") + expect(output).to include(" ✓ create slices/main/repos/book_repo.rb") end it "generates a repo in a nested namespace" do @@ -151,7 +151,7 @@ class DraftRepo < Main::DB::Repo EXPECTED expect(fs.read("slices/main/repos/book/draft_repo.rb")).to eq(repo_file) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/main/repos/book/draft_repo.rb") + expect(output).to include(" ✓ create slices/main/repos/book/draft_repo.rb") end context "with existing file" do diff --git a/spec/unit/hanami/cli/commands/app/generate/slice_spec.rb b/spec/unit/hanami/cli/commands/app/generate/slice_spec.rb index 8da1f7ae..10f760d5 100644 --- a/spec/unit/hanami/cli/commands/app/generate/slice_spec.rb +++ b/spec/unit/hanami/cli/commands/app/generate/slice_spec.rb @@ -47,11 +47,11 @@ class Routes < Hanami::Routes CODE expect(fs.read("config/routes.rb")).to include(routes) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m config/routes.rb") + expect(output).to include(" ✓ create config/routes.rb") # Slice directory expect(fs.directory?("slices/#{slice}")).to be(true) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/#{slice}/") + expect(output).to include(" ✓ create slices/#{slice}/") # Action action = <<~CODE @@ -65,9 +65,9 @@ class Action < #{app}::Action CODE expect(fs.read("slices/#{slice}/action.rb")).to eq(action) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/#{slice}/action.rb") + expect(output).to include(" ✓ create slices/#{slice}/action.rb") expect(fs.read("slices/#{slice}/actions/.keep")).to eq("") - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/#{slice}/actions/.keep") + expect(output).to include(" ✓ create slices/#{slice}/actions/.keep") # Relation relation = <<~EXPECTED @@ -81,9 +81,9 @@ class Relation < Test::DB::Relation end EXPECTED expect(fs.read("slices/admin/db/relation.rb")).to eq(relation) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/admin/db/relation.rb") + expect(output).to include(" ✓ create slices/admin/db/relation.rb") expect(fs.read("slices/admin/relations/.keep")).to eq("") - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/admin/relations/.keep") + expect(output).to include(" ✓ create slices/admin/relations/.keep") # Repo repo = <<~EXPECTED @@ -97,9 +97,9 @@ class Repo < Test::DB::Repo end EXPECTED expect(fs.read("slices/admin/db/repo.rb")).to eq(repo) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/admin/db/repo.rb") + expect(output).to include(" ✓ create slices/admin/db/repo.rb") expect(fs.read("slices/admin/repos/.keep")).to eq("") - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/admin/repos/.keep") + expect(output).to include(" ✓ create slices/admin/repos/.keep") # Struct struct = <<~EXPECTED @@ -113,9 +113,9 @@ class Struct < Test::DB::Struct end EXPECTED expect(fs.read("slices/admin/db/struct.rb")).to eq(struct) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/admin/db/struct.rb") + expect(output).to include(" ✓ create slices/admin/db/struct.rb") expect(fs.read("slices/admin/structs/.keep")).to eq("") - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/admin/structs/.keep") + expect(output).to include(" ✓ create slices/admin/structs/.keep") view = <<~RUBY # auto_register: false @@ -127,7 +127,7 @@ class View < Test::View end RUBY expect(fs.read("slices/#{slice}/view.rb")).to eq(view) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/#{slice}/view.rb") + expect(output).to include(" ✓ create slices/#{slice}/view.rb") helpers = <<~RUBY # auto_register: false @@ -142,7 +142,7 @@ module Helpers end RUBY expect(fs.read("slices/#{slice}/views/helpers.rb")).to eq(helpers) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/#{slice}/views/helpers.rb") + expect(output).to include(" ✓ create slices/#{slice}/views/helpers.rb") operation = <<~RUBY # auto_register: false @@ -154,7 +154,7 @@ class Operation < Test::Operation end RUBY expect(fs.read("slices/#{slice}/operation.rb")).to eq(operation) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/#{slice}/operation.rb") + expect(output).to include(" ✓ create slices/#{slice}/operation.rb") layout = <<~ERB @@ -173,14 +173,14 @@ class Operation < Test::Operation ERB expect(fs.read("slices/#{slice}/templates/layouts/app.html.erb")).to eq(layout) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/#{slice}/templates/layouts/app.html.erb") + expect(output).to include(" ✓ create slices/#{slice}/templates/layouts/app.html.erb") # slices/admin/assets/js/app.js app_js = <<~EXPECTED import "../css/app.css"; EXPECTED expect(fs.read("slices/#{slice}/assets/js/app.js")).to eq(app_js) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/#{slice}/assets/js/app.js") + expect(output).to include(" ✓ create slices/#{slice}/assets/js/app.js") # slices/admin/assets/css/app.css app_css = <<~EXPECTED @@ -191,7 +191,7 @@ class Operation < Test::Operation } EXPECTED expect(fs.read("slices/#{slice}/assets/css/app.css")).to eq(app_css) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/#{slice}/assets/css/app.css") + expect(output).to include(" ✓ create slices/#{slice}/assets/css/app.css") # slices/admin/assets/images/favicon.ico expect(fs.exist?("slices/#{slice}/assets/images/favicon.ico")).to be(true) @@ -228,7 +228,7 @@ class Operation < Test::Operation it "generates multiple slices over time" do within_application_directory do subject.call(name: "admin") - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m config/routes.rb") + expect(output).to include(" ✓ create config/routes.rb") subject.call(name: "billing") @@ -252,7 +252,7 @@ class Routes < Hanami::Routes CODE expect(fs.read("config/routes.rb")).to eq(routes) - expect(output).to include(" \e[36m↻\e[0m \e[36mupdate\e[0m config/routes.rb") + expect(output).to include(" ↻ update config/routes.rb") end end diff --git a/spec/unit/hanami/cli/commands/app/generate/struct_spec.rb b/spec/unit/hanami/cli/commands/app/generate/struct_spec.rb index 3833dfd3..a6c57757 100644 --- a/spec/unit/hanami/cli/commands/app/generate/struct_spec.rb +++ b/spec/unit/hanami/cli/commands/app/generate/struct_spec.rb @@ -28,7 +28,7 @@ class Book < Test::DB::Struct EXPECTED expect(fs.read("app/structs/book.rb")).to eq(struct_file) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/structs/book.rb") + expect(output).to include(" ✓ create app/structs/book.rb") end it "generates a struct in a namespace with default separator" do @@ -48,7 +48,7 @@ class BookDraft < Test::DB::Struct EXPECTED expect(fs.read("app/structs/book/book_draft.rb")).to eq(struct_file) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/structs/book/book_draft.rb") + expect(output).to include(" ✓ create app/structs/book/book_draft.rb") end it "generates an struct in a deep namespace with slash separators" do @@ -70,7 +70,7 @@ class Hardcover < Test::DB::Struct EXPECTED expect(fs.read("app/structs/book/published/hardcover.rb")).to eq(struct_file) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/structs/book/published/hardcover.rb") + expect(output).to include(" ✓ create app/structs/book/published/hardcover.rb") end context "with existing file" do @@ -108,7 +108,7 @@ class Book < Main::DB::Struct EXPECTED expect(fs.read("slices/main/structs/book.rb")).to eq(struct_file) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/main/structs/book.rb") + expect(output).to include(" ✓ create slices/main/structs/book.rb") end it "generates a struct in a nested namespace" do @@ -129,7 +129,7 @@ class DraftBook < Main::DB::Struct EXPECTED expect(fs.read("slices/main/structs/book/draft_book.rb")).to eq(struct_file) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/main/structs/book/draft_book.rb") + expect(output).to include(" ✓ create slices/main/structs/book/draft_book.rb") end context "with existing file" do diff --git a/spec/unit/hanami/cli/commands/app/generate/view_spec.rb b/spec/unit/hanami/cli/commands/app/generate/view_spec.rb index 514efb0e..899e1884 100644 --- a/spec/unit/hanami/cli/commands/app/generate/view_spec.rb +++ b/spec/unit/hanami/cli/commands/app/generate/view_spec.rb @@ -45,7 +45,7 @@ class Index < Test::View EXPECTED expect(fs.read("app/views/users/index.rb")).to eq(view_file) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/views/users/index.rb") + expect(output).to include(" ✓ create app/views/users/index.rb") # template expect(fs.directory?("app/templates/users")).to be(true) @@ -55,7 +55,7 @@ class Index < Test::View EXPECTED expect(fs.read("app/templates/users/index.html.erb")).to eq(template_file) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/templates/users/index.html.erb") + expect(output).to include(" ✓ create app/templates/users/index.html.erb") end end @@ -80,7 +80,7 @@ class Index < Test::View EXPECTED expect(fs.read("app/views/special/users/index.rb")).to eq(view_file) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/views/special/users/index.rb") + expect(output).to include(" ✓ create app/views/special/users/index.rb") # template expect(fs.directory?("app/templates/special/users")).to be(true) @@ -90,7 +90,7 @@ class Index < Test::View EXPECTED expect(fs.read("app/templates/special/users/index.html.erb")).to eq(template_file) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m app/templates/special/users/index.html.erb") + expect(output).to include(" ✓ create app/templates/special/users/index.html.erb") end end @@ -156,7 +156,7 @@ class Index < Main::View EXPECTED expect(fs.read("slices/main/views/users/index.rb")).to eq(view_file) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/main/views/users/index.rb") + expect(output).to include(" ✓ create slices/main/views/users/index.rb") # template expect(fs.directory?("slices/main/templates/users")).to be(true) @@ -166,7 +166,7 @@ class Index < Main::View EXPECTED expect(fs.read("slices/main/templates/users/index.html.erb")).to eq(template_file) - expect(output).to include(" \e[32m✓\e[0m \e[32mcreate\e[0m slices/main/templates/users/index.html.erb") + expect(output).to include(" ✓ create slices/main/templates/users/index.html.erb") end end diff --git a/spec/unit/hanami/cli/commands/gem/new_spec.rb b/spec/unit/hanami/cli/commands/gem/new_spec.rb index ccd8cd1e..c54ca83e 100644 --- a/spec/unit/hanami/cli/commands/gem/new_spec.rb +++ b/spec/unit/hanami/cli/commands/gem/new_spec.rb @@ -102,11 +102,11 @@ subject.call(app: app, **kwargs) expect(fs.directory?(app)).to be(true) - expect(output).to include(Hanami::CLI::Formatter.created_directory("#{app}/")) + expect(output).to include("✓ create directory #{app}/") expect(output).to include("-> Entering `#{app}/` directory...") - expect(output).to include(Hanami::CLI::Formatter.info("Installing dependencies...")) - expect(output).to include(Hanami::CLI::Formatter.info("Installing npm packages...")) - expect(output).to include(Hanami::CLI::Formatter.info("Running hanami install...")) + expect(output).to include("→ Installing dependencies...") + expect(output).to include("→ Installing npm packages...") + expect(output).to include("→ Running hanami install...") fs.chdir(app) do # .gitignore @@ -120,7 +120,7 @@ db/*.sqlite EXPECTED expect(fs.read(".gitignore")).to eq(gitignore) - expect(output).to include(Hanami::CLI::Formatter.created(".gitignore")) + expect(output).to include(" ✓ create .gitignore") # .env env = <<~EXPECTED @@ -128,7 +128,7 @@ DATABASE_URL=sqlite://db/#{app}.sqlite EXPECTED expect(fs.read(".env")).to eq(env) - expect(output).to include(Hanami::CLI::Formatter.created(".env")) + expect(output).to include(" ✓ create .env") # README.md readme = <<~EXPECTED @@ -149,7 +149,7 @@ - [Hanami API Doc](https://gemdocs.org/gems/hanami/latest) EXPECTED expect(fs.read("README.md")).to eq(readme) - expect(output).to include(Hanami::CLI::Formatter.created("README.md")) + expect(output).to include(" ✓ create README.md") # Gemfile hanami_version = Hanami::CLI::Generators::Version.gem_requirement @@ -189,7 +189,7 @@ end EXPECTED expect(fs.read("Gemfile")).to eq(gemfile) - expect(output).to include(Hanami::CLI::Formatter.created("Gemfile")) + expect(output).to include(" ✓ create Gemfile") # package.json hanami_npm_version = Hanami::CLI::Generators::Version.npm_package_requirement @@ -204,7 +204,7 @@ } EXPECTED expect(fs.read("package.json")).to eq(package_json) - expect(output).to include(Hanami::CLI::Formatter.created("package.json")) + expect(output).to include(" ✓ create package.json") # Procfile.dev procfile = <<~EXPECTED @@ -212,7 +212,7 @@ assets: bundle exec hanami assets watch EXPECTED expect(fs.read("Procfile.dev")).to eq(procfile) - expect(output).to include(Hanami::CLI::Formatter.created("Procfile.dev")) + expect(output).to include(" ✓ create Procfile.dev") # Rakefile rakefile = <<~EXPECTED @@ -224,7 +224,7 @@ Rake.add_rakelib "lib/tasks" EXPECTED expect(fs.read("Rakefile")).to eq(rakefile) - expect(output).to include(Hanami::CLI::Formatter.created("Rakefile")) + expect(output).to include(" ✓ create Rakefile") # config.ru config_ru = <<~EXPECTED @@ -235,7 +235,7 @@ run Hanami.app EXPECTED expect(fs.read("config.ru")).to eq(config_ru) - expect(output).to include(Hanami::CLI::Formatter.created("config.ru")) + expect(output).to include(" ✓ create config.ru") # bin/dev bin_dev = <<~EXPECTED @@ -250,7 +250,7 @@ EXPECTED expect(fs.read("bin/dev")).to eq(bin_dev) expect(fs.executable?("bin/dev")).to be(true) - expect(output).to include(Hanami::CLI::Formatter.created("bin/dev")) + expect(output).to include(" ✓ create bin/dev") # config/app.rb hanami_app = <<~EXPECTED @@ -264,7 +264,7 @@ class App < Hanami::App end EXPECTED expect(fs.read("config/app.rb")).to eq(hanami_app) - expect(output).to include(Hanami::CLI::Formatter.created("config/app.rb")) + expect(output).to include(" ✓ create config/app.rb") # config/assets.js assets = <<~EXPECTED @@ -287,7 +287,7 @@ class App < Hanami::App }); EXPECTED expect(fs.read("config/assets.js")).to eq(assets) - expect(output).to include(Hanami::CLI::Formatter.created("config/assets.js")) + expect(output).to include(" ✓ create config/assets.js") # config/settings.rb settings = <<~EXPECTED @@ -302,7 +302,7 @@ class Settings < Hanami::Settings end EXPECTED expect(fs.read("config/settings.rb")).to eq(settings) - expect(output).to include(Hanami::CLI::Formatter.created("config/settings.rb")) + expect(output).to include(" ✓ create config/settings.rb") # config/routes.rb routes = <<~EXPECTED @@ -315,7 +315,7 @@ class Routes < Hanami::Routes end EXPECTED expect(fs.read("config/routes.rb")).to eq(routes) - expect(output).to include(Hanami::CLI::Formatter.created("config/routes.rb")) + expect(output).to include(" ✓ create config/routes.rb") # config/puma.rb puma = <<~EXPECTED @@ -368,13 +368,13 @@ class Routes < Hanami::Routes end EXPECTED expect(fs.read("config/puma.rb")).to eq(puma) - expect(output).to include(Hanami::CLI::Formatter.created("config/puma.rb")) + expect(output).to include(" ✓ create config/puma.rb") # lib/tasks/.keep tasks_keep = <<~EXPECTED EXPECTED expect(fs.read("lib/tasks/.keep")).to eq(tasks_keep) - expect(output).to include(Hanami::CLI::Formatter.created("lib/tasks/.keep")) + expect(output).to include(" ✓ create lib/tasks/.keep") # app/action.rb action = <<~EXPECTED @@ -392,7 +392,7 @@ class Action < Hanami::Action end EXPECTED expect(fs.read("app/action.rb")).to eq(action) - expect(output).to include(Hanami::CLI::Formatter.created("app/action.rb")) + expect(output).to include(" ✓ create app/action.rb") # app/view.rb view = <<~RUBY @@ -407,7 +407,7 @@ class View < Hanami::View end RUBY expect(fs.read("app/view.rb")).to eq(view) - expect(output).to include(Hanami::CLI::Formatter.created("app/view.rb")) + expect(output).to include(" ✓ create app/view.rb") # app/views/helpers.rb helpers = <<~RUBY @@ -423,7 +423,7 @@ module Helpers end RUBY expect(fs.read("app/views/helpers.rb")).to eq(helpers) - expect(output).to include(Hanami::CLI::Formatter.created("app/views/helpers.rb")) + expect(output).to include(" ✓ create app/views/helpers.rb") # app/templates/layouts/app.html.erb layout = <<~ERB @@ -443,14 +443,14 @@ module Helpers ERB expect(fs.read("app/templates/layouts/app.html.erb")).to eq(layout) - expect(output).to include(Hanami::CLI::Formatter.created("app/templates/layouts/app.html.erb")) + expect(output).to include(" ✓ create app/templates/layouts/app.html.erb") # app/assets/js/app.js app_js = <<~EXPECTED import "../css/app.css"; EXPECTED expect(fs.read("app/assets/js/app.js")).to eq(app_js) - expect(output).to include(Hanami::CLI::Formatter.created("app/assets/js/app.js")) + expect(output).to include(" ✓ create app/assets/js/app.js") # app/assets/css/app.css app_css = <<~EXPECTED @@ -461,7 +461,7 @@ module Helpers } EXPECTED expect(fs.read("app/assets/css/app.css")).to eq(app_css) - expect(output).to include(Hanami::CLI::Formatter.created("app/assets/css/app.css")) + expect(output).to include(" ✓ create app/assets/css/app.css") # app/assets/images/favicon.ico expect(fs.exist?("app/assets/images/favicon.ico")).to be(true) @@ -481,7 +481,7 @@ module Types end EXPECTED expect(fs.read("lib/#{app}/types.rb")).to eq(types) - expect(output).to include(Hanami::CLI::Formatter.created("lib/bookshelf/types.rb")) + expect(output).to include(" ✓ create lib/bookshelf/types.rb") # app/operation.rb action = <<~EXPECTED @@ -496,7 +496,7 @@ class Operation < Dry::Operation end EXPECTED expect(fs.read("app/operation.rb")).to eq(action) - expect(output).to include(Hanami::CLI::Formatter.created("app/operation.rb")) + expect(output).to include(" ✓ create app/operation.rb") # public/ error pages expect(fs.read("public/404.html")).to include %(The page you were looking for doesn’t exist (404)) @@ -563,7 +563,7 @@ class Operation < Dry::Operation end EXPECTED expect(fs.read("Gemfile")).to eq(gemfile) - expect(output).to include(Hanami::CLI::Formatter.created("Gemfile")) + expect(output).to include(" ✓ create Gemfile") end end end @@ -587,11 +587,11 @@ class Operation < Dry::Operation subject.call(app: app, **kwargs) expect(fs.directory?(app)).to be(true) - expect(output).to include(Hanami::CLI::Formatter.created_directory("#{app}/")) + expect(output).to include("✓ create directory #{app}/") expect(output).to include("-> Entering `#{app}/` directory...") - expect(output).to include(Hanami::CLI::Formatter.info("Installing dependencies...")) - expect(output).to include(Hanami::CLI::Formatter.info("Installing npm packages...")) - expect(output).to include(Hanami::CLI::Formatter.info("Running hanami install...")) + expect(output).to include("→ Installing dependencies...") + expect(output).to include("→ Installing npm packages...") + expect(output).to include("→ Running hanami install...") fs.chdir(app) do # .gitignore @@ -605,7 +605,7 @@ class Operation < Dry::Operation db/*.sqlite EXPECTED expect(fs.read(".gitignore")).to eq(gitignore) - expect(output).to include(Hanami::CLI::Formatter.created(".gitignore")) + expect(output).to include(" ✓ create .gitignore") # .env env = <<~EXPECTED @@ -613,7 +613,7 @@ class Operation < Dry::Operation DATABASE_URL=sqlite://db/#{app}.sqlite EXPECTED expect(fs.read(".env")).to eq(env) - expect(output).to include(Hanami::CLI::Formatter.created(".env")) + expect(output).to include(" ✓ create .env") # README.md readme = <<~EXPECTED @@ -634,7 +634,7 @@ class Operation < Dry::Operation - [Hanami API Doc](https://gemdocs.org/gems/hanami/latest) EXPECTED expect(fs.read("README.md")).to eq(readme) - expect(output).to include(Hanami::CLI::Formatter.created("README.md")) + expect(output).to include(" ✓ create README.md") # Gemfile hanami_version = Hanami::CLI::Generators::Version.gem_requirement @@ -674,7 +674,7 @@ class Operation < Dry::Operation end EXPECTED expect(fs.read("Gemfile")).to eq(gemfile) - expect(output).to include(Hanami::CLI::Formatter.created("Gemfile")) + expect(output).to include(" ✓ create Gemfile") # package.json hanami_npm_version = Hanami::CLI::Generators::Version.npm_package_requirement @@ -689,7 +689,7 @@ class Operation < Dry::Operation } EXPECTED expect(fs.read("package.json")).to eq(package_json) - expect(output).to include(Hanami::CLI::Formatter.created("package.json")) + expect(output).to include(" ✓ create package.json") # Procfile.dev procfile = <<~EXPECTED @@ -697,7 +697,7 @@ class Operation < Dry::Operation assets: bundle exec hanami assets watch EXPECTED expect(fs.read("Procfile.dev")).to eq(procfile) - expect(output).to include(Hanami::CLI::Formatter.created("Procfile.dev")) + expect(output).to include(" ✓ create Procfile.dev") # Rakefile rakefile = <<~EXPECTED @@ -709,7 +709,7 @@ class Operation < Dry::Operation Rake.add_rakelib "lib/tasks" EXPECTED expect(fs.read("Rakefile")).to eq(rakefile) - expect(output).to include(Hanami::CLI::Formatter.created("Rakefile")) + expect(output).to include(" ✓ create Rakefile") # config.ru config_ru = <<~EXPECTED @@ -720,7 +720,7 @@ class Operation < Dry::Operation run Hanami.app EXPECTED expect(fs.read("config.ru")).to eq(config_ru) - expect(output).to include(Hanami::CLI::Formatter.created("config.ru")) + expect(output).to include(" ✓ create config.ru") # bin/dev bin_dev = <<~EXPECTED @@ -735,7 +735,7 @@ class Operation < Dry::Operation EXPECTED expect(fs.read("bin/dev")).to eq(bin_dev) expect(fs.executable?("bin/dev")).to be(true) - expect(output).to include(Hanami::CLI::Formatter.created("bin/dev")) + expect(output).to include(" ✓ create bin/dev") # config/app.rb hanami_app = <<~EXPECTED @@ -749,7 +749,7 @@ class App < Hanami::App end EXPECTED expect(fs.read("config/app.rb")).to eq(hanami_app) - expect(output).to include(Hanami::CLI::Formatter.created("config/app.rb")) + expect(output).to include(" ✓ create config/app.rb") # config/assets.js assets = <<~EXPECTED @@ -772,7 +772,7 @@ class App < Hanami::App }); EXPECTED expect(fs.read("config/assets.js")).to eq(assets) - expect(output).to include(Hanami::CLI::Formatter.created("config/assets.js")) + expect(output).to include(" ✓ create config/assets.js") # config/settings.rb settings = <<~EXPECTED @@ -787,7 +787,7 @@ class Settings < Hanami::Settings end EXPECTED expect(fs.read("config/settings.rb")).to eq(settings) - expect(output).to include(Hanami::CLI::Formatter.created("config/settings.rb")) + expect(output).to include(" ✓ create config/settings.rb") # config/routes.rb routes = <<~EXPECTED @@ -800,7 +800,7 @@ class Routes < Hanami::Routes end EXPECTED expect(fs.read("config/routes.rb")).to eq(routes) - expect(output).to include(Hanami::CLI::Formatter.created("config/routes.rb")) + expect(output).to include(" ✓ create config/routes.rb") # config/puma.rb puma = <<~EXPECTED @@ -853,13 +853,13 @@ class Routes < Hanami::Routes end EXPECTED expect(fs.read("config/puma.rb")).to eq(puma) - expect(output).to include(Hanami::CLI::Formatter.created("config/puma.rb")) + expect(output).to include(" ✓ create config/puma.rb") # lib/tasks/.keep tasks_keep = <<~EXPECTED EXPECTED expect(fs.read("lib/tasks/.keep")).to eq(tasks_keep) - expect(output).to include(Hanami::CLI::Formatter.created("lib/tasks/.keep")) + expect(output).to include(" ✓ create lib/tasks/.keep") # app/action.rb action = <<~EXPECTED @@ -877,9 +877,9 @@ class Action < Hanami::Action end EXPECTED expect(fs.read("app/action.rb")).to eq(action) - expect(output).to include(Hanami::CLI::Formatter.created("app/action.rb")) + expect(output).to include(" ✓ create app/action.rb") expect(fs.read("app/actions/.keep")).to eq("") - expect(output).to include(Hanami::CLI::Formatter.created("app/actions/.keep")) + expect(output).to include(" ✓ create app/actions/.keep") # app/view.rb view = <<~RUBY @@ -894,7 +894,7 @@ class View < Hanami::View end RUBY expect(fs.read("app/view.rb")).to eq(view) - expect(output).to include(Hanami::CLI::Formatter.created("app/view.rb")) + expect(output).to include(" ✓ create app/view.rb") # app/views/helpers.rb helpers = <<~RUBY @@ -910,7 +910,7 @@ module Helpers end RUBY expect(fs.read("app/views/helpers.rb")).to eq(helpers) - expect(output).to include(Hanami::CLI::Formatter.created("app/views/helpers.rb")) + expect(output).to include(" ✓ create app/views/helpers.rb") # app/templates/layouts/app.html.erb layout = <<~ERB @@ -930,14 +930,14 @@ module Helpers ERB expect(fs.read("app/templates/layouts/app.html.erb")).to eq(layout) - expect(output).to include(Hanami::CLI::Formatter.created("app/templates/layouts/app.html.erb")) + expect(output).to include(" ✓ create app/templates/layouts/app.html.erb") # app/assets/js/app.js app_js = <<~EXPECTED import "../css/app.css"; EXPECTED expect(fs.read("app/assets/js/app.js")).to eq(app_js) - expect(output).to include(Hanami::CLI::Formatter.created("app/assets/js/app.js")) + expect(output).to include(" ✓ create app/assets/js/app.js") # app/assets/css/app.css app_css = <<~EXPECTED @@ -948,7 +948,7 @@ module Helpers } EXPECTED expect(fs.read("app/assets/css/app.css")).to eq(app_css) - expect(output).to include(Hanami::CLI::Formatter.created("app/assets/css/app.css")) + expect(output).to include(" ✓ create app/assets/css/app.css") # app/assets/images/favicon.ico expect(fs.exist?("app/assets/images/favicon.ico")).to be(true) @@ -967,9 +967,9 @@ class Relation < Hanami::DB::Relation end EXPECTED expect(fs.read("app/db/relation.rb")).to eq(relation) - expect(output).to include(Hanami::CLI::Formatter.created("app/db/relation.rb")) + expect(output).to include(" ✓ create app/db/relation.rb") expect(fs.read("app/relations/.keep")).to eq("") - expect(output).to include(Hanami::CLI::Formatter.created("app/relations/.keep")) + expect(output).to include(" ✓ create app/relations/.keep") # app/db/repo.rb repo = <<~EXPECTED @@ -985,9 +985,9 @@ class Repo < Hanami::DB::Repo end EXPECTED expect(fs.read("app/db/repo.rb")).to eq(repo) - expect(output).to include(Hanami::CLI::Formatter.created("app/db/repo.rb")) + expect(output).to include(" ✓ create app/db/repo.rb") expect(fs.read("app/repos/.keep")).to eq("") - expect(output).to include(Hanami::CLI::Formatter.created("app/repos/.keep")) + expect(output).to include(" ✓ create app/repos/.keep") # app/db/struct.rb struct = <<~EXPECTED @@ -1003,9 +1003,9 @@ class Struct < Hanami::DB::Struct end EXPECTED expect(fs.read("app/db/struct.rb")).to eq(struct) - expect(output).to include(Hanami::CLI::Formatter.created("app/db/struct.rb")) + expect(output).to include(" ✓ create app/db/struct.rb") expect(fs.read("app/structs/.keep")).to eq("") - expect(output).to include(Hanami::CLI::Formatter.created("app/structs/.keep")) + expect(output).to include(" ✓ create app/structs/.keep") seeds = <<~EXPECTED # This seeds file should create the database records required to run the app. @@ -1025,13 +1025,13 @@ class Struct < Hanami::DB::Struct # categories.insert(title: "General") EXPECTED expect(fs.read("config/db/seeds.rb")).to eq(seeds) - expect(output).to include(Hanami::CLI::Formatter.created("config/db/seeds.rb")) + expect(output).to include(" ✓ create config/db/seeds.rb") expect(fs.read("config/db/migrate/.keep")).to eq("") - expect(output).to include(Hanami::CLI::Formatter.created("config/db/migrate/.keep")) + expect(output).to include(" ✓ create config/db/migrate/.keep") expect(fs.read("db/.keep")).to eq("") - expect(output).to include(Hanami::CLI::Formatter.created("db/.keep")) + expect(output).to include(" ✓ create db/.keep") # lib/bookshelf/types.rb types = <<~EXPECTED @@ -1048,7 +1048,7 @@ module Types end EXPECTED expect(fs.read("lib/#{app}/types.rb")).to eq(types) - expect(output).to include(Hanami::CLI::Formatter.created("lib/bookshelf/types.rb")) + expect(output).to include(" ✓ create lib/bookshelf/types.rb") # public/ error pages expect(fs.read("public/404.html")).to include %(The page you were looking for doesn’t exist (404)) @@ -1412,7 +1412,7 @@ class App < Hanami::App subject.call(app: app, **kwargs) expect(fs.directory?(app)).to be(true) - expect(output).to include(Hanami::CLI::Formatter.info("Running bundle binstubs hanami-cli rake...")) + expect(output).to include("→ Running bundle binstubs hanami-cli rake...") end it "initializes a git repository" do @@ -1438,6 +1438,6 @@ class App < Hanami::App subject.call(app: app, **kwargs) expect(fs.directory?(app)).to be(true) - expect(output).to include(Hanami::CLI::Formatter.info("Initializing git repository...")) + expect(output).to include("→ Initializing git repository...") end end