From e34a04bc7b0c0446623f13a0179975ba10843354 Mon Sep 17 00:00:00 2001 From: Austin Kabiru Date: Fri, 4 Jan 2019 23:06:31 +0300 Subject: [PATCH 01/15] feat(cli): Pull in fakerbot gem logic --- lib/faker/cli.rb | 51 ++++++++++++++++++ lib/faker/cli/command.rb | 19 +++++++ lib/faker/cli/commands/list.rb | 20 +++++++ lib/faker/cli/commands/search.rb | 30 +++++++++++ lib/faker/cli/reflector.rb | 81 ++++++++++++++++++++++++++++ lib/faker/cli/renderer.rb | 91 ++++++++++++++++++++++++++++++++ 6 files changed, 292 insertions(+) create mode 100644 lib/faker/cli.rb create mode 100644 lib/faker/cli/command.rb create mode 100644 lib/faker/cli/commands/list.rb create mode 100644 lib/faker/cli/commands/search.rb create mode 100644 lib/faker/cli/reflector.rb create mode 100644 lib/faker/cli/renderer.rb diff --git a/lib/faker/cli.rb b/lib/faker/cli.rb new file mode 100644 index 0000000000..37148616d4 --- /dev/null +++ b/lib/faker/cli.rb @@ -0,0 +1,51 @@ +# frozen_string_literal: true + +require 'thor' +require 'faker/version' +require 'faker/cli/commands/list' +require 'faker/cli/commands/search' + +module Faker + module CLI + class Base < Thor + Error = Class.new(StandardError) + + desc 'version', 'Faker version' + def version + require_relative 'version' + puts "v#{Faker::VERSION}" + end + map %w[--version -v] => :version + + desc 'list', 'List all Faker constants' + method_option :help, aliases: '-h', type: :boolean, + desc: 'Display usage information' + method_option :show_methods, aliases: '-m', type: :boolean, default: true, + desc: 'Display Faker constants with methods' + method_option :verbose, aliases: '-v', type: :boolean, + desc: 'Include sample Faker output' + def list(*) + if options[:help] + invoke :help, ['list'] + else + Faker::CLI::Commands::List.new(options).execute + end + end + + desc 'search [Faker]', 'Search Faker method(s)' + method_option :help, aliases: '-h', type: :boolean, + desc: 'Display usage information' + method_option :show_methods, aliases: '-m', type: :boolean, default: true, + desc: 'Display Faker constants with methods' + method_option :verbose, aliases: '-v', type: :boolean, + desc: 'Include sample Faker output' + def search(query) + if options[:help] + invoke :help, ['search'] + else + Faker::CLI::Commands::Search.new(options).execute(query) + end + end + end + end +end diff --git a/lib/faker/cli/command.rb b/lib/faker/cli/command.rb new file mode 100644 index 0000000000..e550422f4c --- /dev/null +++ b/lib/faker/cli/command.rb @@ -0,0 +1,19 @@ +require 'forwardable' + +require_relative 'reflector' +require_relative 'renderer' + +module Faker + module CLI + class Command + extend Forwardable + + def_delegators :command, :run + attr_reader :options + + def render(result, output) + Renderer.call(result, options, output) + end + end + end +end diff --git a/lib/faker/cli/commands/list.rb b/lib/faker/cli/commands/list.rb new file mode 100644 index 0000000000..fc26fe64f6 --- /dev/null +++ b/lib/faker/cli/commands/list.rb @@ -0,0 +1,20 @@ +require_relative '../command' + +module Faker + module CLI + module Commands + class List < Faker::CLI::Command + def initialize(options) + @options = options + end + + def execute(output: $stdout) + result = Faker::CLI::Reflector.list( + show_methods: options[:show_methods] + ) + render(result, output) + end + end + end + end +end diff --git a/lib/faker/cli/commands/search.rb b/lib/faker/cli/commands/search.rb new file mode 100644 index 0000000000..e962fd1d50 --- /dev/null +++ b/lib/faker/cli/commands/search.rb @@ -0,0 +1,30 @@ +require_relative '../command' + +module Faker + module CLI + module Commands + class Search < Faker::CLI::Command + def initialize(options) + @options = options + end + + def execute(input, output: $stdout) + result = Faker::CLI::Reflector.find(input) + render(result, output) + end + + private + + def render(result, output) + return not_found if result.empty? + + super(result, output) + end + + def not_found + puts "\nSorry, we couldn't find a match šŸ˜¢", "\n" + end + end + end + end +end diff --git a/lib/faker/cli/reflector.rb b/lib/faker/cli/reflector.rb new file mode 100644 index 0000000000..796a3fdc8b --- /dev/null +++ b/lib/faker/cli/reflector.rb @@ -0,0 +1,81 @@ +module Faker + module CLI + # Exposes `Faker` reflection methods + # @api private + class Reflector + Faker::Base.class_eval do + # Select `Faker` subclasses + # @return [Array] `Faker::Base` sub classes + def self.descendants + @descendants ||= ObjectSpace.each_object(Class).select do |klass| + klass < self + end + end + + # Select public class methods + # @return [Array] public methods + def self.my_singleton_methods + singleton_methods(false).select { |m| respond_to?(m) } + end + end + + attr_reader :descendants_with_methods, :query + + def initialize(query = nil) + @descendants_with_methods = Hash.new { |h, k| h[k] = [] } + @query = query + end + + class << self + def find(query) + new(query).find + end + + def list(show_methods: false) + new.list(show_methods) + end + end + + def find + search_descendants_matching_query + descendants_with_methods + end + + def list(show_methods) + show_methods ? all_descendants_with_methods : faker_descendants + end + + private + + def all_descendants_with_methods + faker_descendants.each do |faker| + store(faker, faker.my_singleton_methods) + end + descendants_with_methods + end + + def search_descendants_matching_query + faker_descendants.each do |faker| + methods = faker.my_singleton_methods + matching = methods.select { |m| query_matches?(m.to_s) } + store(faker, matching) + end + end + + def query_matches?(method_name) + method_name_parts = method_name.split(/_/).reject(&:empty?) + query.match(/#{method_name_parts.join('|')}/) + end + + def store(descendant, methods) + return if methods.empty? + + descendants_with_methods[descendant].concat(methods) + end + + def faker_descendants + @faker_descendants ||= Faker::Base.descendants + end + end + end +end diff --git a/lib/faker/cli/renderer.rb b/lib/faker/cli/renderer.rb new file mode 100644 index 0000000000..c2455dabb7 --- /dev/null +++ b/lib/faker/cli/renderer.rb @@ -0,0 +1,91 @@ +require 'pastel' +require 'tty/pager' +require 'tty/screen' +require 'tty/tree' + +module Faker + module CLI + class Renderer + attr_reader :crayon, :hash, :options, :output, :pager + + def self.call(*args) + new(*args).call + end + + def initialize(hash, options, output) + @hash = hash + @options = options.deep_symbolize_keys + @output = output + @crayon = Pastel.new(enabled: output.tty?) + @pager = TTY::Pager.new(command: 'less -R') + end + + def call + if paginable? + pager.page(render) + else + output.puts(render) + end + end + + def render + tree.render + end + + def tree + @tree ||= TTY::Tree.new(build_tree) + end + + def paginable? + gt_screen_height? && output.tty? + end + + def gt_screen_height? + tree.nodes.size > TTY::Screen.height + end + + private + + def build_tree + result = hash.reduce({}) do |h, (faker, methods)| + h.merge! node(faker, methods&.sort) + end + + result.sort_by(&:to_s).to_h + end + + def node(const, methods) + { + crayon.green(const.to_s) => leaf(const, methods) + } + end + + def leaf(const, methods) + (methods || []).map { |m| crayon.cyan(*leaf_args(m, const)) } + end + + def leaf_args(method, const) + [method.to_s].tap { |arr| verbose_output(method, const, arr) if verbose? } + end + + def verbose? + options[:verbose] == true + end + + def verbose_output(method, const, arr) + fake, message = faker_method(method, const) + arr << crayon.dim.white("=> #{fake}") << crayon.dim.magenta.bold(message.to_s) + end + + def faker_method(method, const) + [const.public_send(method), ensure_method_is_supported(method, const)] + rescue ArgumentError => _exception + ['N/A', ''] + end + + def ensure_method_is_supported(method, const) + const.respond_to?(:"_deprecated_#{method}") ? ' ( WILL BE DEPRECATED )' : '' + end + end + end +end From 552de6ede3ff05b401b384d18410781b7a272061 Mon Sep 17 00:00:00 2001 From: Austin Kabiru Date: Sat, 5 Jan 2019 00:03:08 +0300 Subject: [PATCH 02/15] chore(cli): Extract module outside of `faker` dir The module dir `faker` houses the main "faker" namespaces; and it should remain that way. Best to have the CLI live outside the directory; similar to helpers --- lib/{faker => }/cli.rb | 5 +++-- lib/{faker => }/cli/command.rb | 2 ++ lib/{faker => }/cli/commands/list.rb | 2 ++ lib/{faker => }/cli/commands/search.rb | 2 ++ lib/{faker => }/cli/reflector.rb | 4 ++++ lib/{faker => }/cli/renderer.rb | 6 ++++-- test/test_determinism.rb | 2 +- 7 files changed, 18 insertions(+), 5 deletions(-) rename lib/{faker => }/cli.rb (95%) rename lib/{faker => }/cli/command.rb (91%) rename lib/{faker => }/cli/commands/list.rb (92%) rename lib/{faker => }/cli/commands/search.rb (95%) rename lib/{faker => }/cli/reflector.rb (97%) rename lib/{faker => }/cli/renderer.rb (95%) diff --git a/lib/faker/cli.rb b/lib/cli.rb similarity index 95% rename from lib/faker/cli.rb rename to lib/cli.rb index 37148616d4..a1e595529d 100644 --- a/lib/faker/cli.rb +++ b/lib/cli.rb @@ -1,9 +1,10 @@ # frozen_string_literal: true require 'thor' + +require 'cli/commands/list' +require 'cli/commands/search' require 'faker/version' -require 'faker/cli/commands/list' -require 'faker/cli/commands/search' module Faker module CLI diff --git a/lib/faker/cli/command.rb b/lib/cli/command.rb similarity index 91% rename from lib/faker/cli/command.rb rename to lib/cli/command.rb index e550422f4c..3140a38462 100644 --- a/lib/faker/cli/command.rb +++ b/lib/cli/command.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'forwardable' require_relative 'reflector' diff --git a/lib/faker/cli/commands/list.rb b/lib/cli/commands/list.rb similarity index 92% rename from lib/faker/cli/commands/list.rb rename to lib/cli/commands/list.rb index fc26fe64f6..9aa42e8ec3 100644 --- a/lib/faker/cli/commands/list.rb +++ b/lib/cli/commands/list.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require_relative '../command' module Faker diff --git a/lib/faker/cli/commands/search.rb b/lib/cli/commands/search.rb similarity index 95% rename from lib/faker/cli/commands/search.rb rename to lib/cli/commands/search.rb index e962fd1d50..27f7cb75aa 100644 --- a/lib/faker/cli/commands/search.rb +++ b/lib/cli/commands/search.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require_relative '../command' module Faker diff --git a/lib/faker/cli/reflector.rb b/lib/cli/reflector.rb similarity index 97% rename from lib/faker/cli/reflector.rb rename to lib/cli/reflector.rb index 796a3fdc8b..2af3bdea13 100644 --- a/lib/faker/cli/reflector.rb +++ b/lib/cli/reflector.rb @@ -1,3 +1,7 @@ +# frozen_string_literal: true + +require 'faker' + module Faker module CLI # Exposes `Faker` reflection methods diff --git a/lib/faker/cli/renderer.rb b/lib/cli/renderer.rb similarity index 95% rename from lib/faker/cli/renderer.rb rename to lib/cli/renderer.rb index c2455dabb7..12850949f1 100644 --- a/lib/faker/cli/renderer.rb +++ b/lib/cli/renderer.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'pastel' require 'tty/pager' require 'tty/screen' @@ -14,7 +16,7 @@ def self.call(*args) def initialize(hash, options, output) @hash = hash - @options = options.deep_symbolize_keys + @options = options @output = output @crayon = Pastel.new(enabled: output.tty?) @pager = TTY::Pager.new(command: 'less -R') @@ -69,7 +71,7 @@ def leaf_args(method, const) end def verbose? - options[:verbose] == true + options[:verbose] end def verbose_output(method, const, arr) diff --git a/test/test_determinism.rb b/test/test_determinism.rb index ff6fa92609..7630b96732 100644 --- a/test/test_determinism.rb +++ b/test/test_determinism.rb @@ -45,7 +45,7 @@ def all_methods def subclasses Faker.constants.delete_if do |subclass| - %i[Base Bank Books Cat Char Base58 ChileRut Config Creature Date Dog DragonBall Dota ElderScrolls Fallout Games GamesHalfLife HeroesOfTheStorm Internet JapaneseMedia LeagueOfLegends Movies Myst Overwatch OnePiece Pokemon SwordArtOnline TvShows Time VERSION Witcher WorldOfWarcraft Zelda].include?(subclass) + %i[Base Bank Books Cat Char Base58 ChileRut CLI Config Creature Date Dog DragonBall Dota ElderScrolls Fallout Games GamesHalfLife HeroesOfTheStorm Internet JapaneseMedia LeagueOfLegends Movies Myst Overwatch OnePiece Pokemon SwordArtOnline TvShows Time VERSION Witcher WorldOfWarcraft Zelda].include?(subclass) end.sort end From 2582f5d5732260d987ee2b166e0f4d8fdf0f3137 Mon Sep 17 00:00:00 2001 From: Austin Kabiru Date: Sat, 5 Jan 2019 00:06:16 +0300 Subject: [PATCH 03/15] feat(cli): Add `faker` excecutable --- Gemfile.lock | 55 ++++++++++++++++++++++++++++++++++++++++----------- bin/faker | 19 ++++++++++++++++++ faker.gemspec | 51 ++++++++++++++++++++++++++++------------------- 3 files changed, 93 insertions(+), 32 deletions(-) create mode 100755 bin/faker diff --git a/Gemfile.lock b/Gemfile.lock index bcf6e3c3fd..74789e2448 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -3,26 +3,40 @@ PATH specs: faker (1.9.1) i18n (>= 0.7) + pastel (~> 0.7.2) + thor (~> 0.20.0) + tty-pager (~> 0.12.0) + tty-screen (~> 0.6.5) + tty-tree (~> 0.2.0) GEM remote: https://rubygems.org/ specs: ast (2.4.0) - concurrent-ruby (1.0.5) + coderay (1.1.2) + concurrent-ruby (1.1.4) docile (1.3.1) - i18n (1.1.1) + equatable (0.5.0) + i18n (1.4.0) concurrent-ruby (~> 1.0) - jaro_winkler (1.5.1) + jaro_winkler (1.5.2) json (2.1.0) + method_source (0.9.2) minitest (5.11.3) parallel (1.12.1) - parser (2.5.1.2) + parser (2.5.3.0) ast (~> 2.4.0) + pastel (0.7.2) + equatable (~> 0.5.0) + tty-color (~> 0.4.0) power_assert (1.1.3) powerpack (0.1.2) + pry (0.12.2) + coderay (~> 1.1.0) + method_source (~> 0.9.0) rainbow (3.0.0) rake (12.3.1) - rubocop (0.59.2) + rubocop (0.59.1) jaro_winkler (~> 1.5.1) parallel (~> 1.10) parser (>= 2.5, != 2.5.1.1) @@ -36,22 +50,39 @@ GEM json (>= 1.8, < 3) simplecov-html (~> 0.10.0) simplecov-html (0.10.2) + strings (0.1.4) + strings-ansi (~> 0.1.0) + unicode-display_width (~> 1.4.0) + unicode_utils (~> 1.4.0) + strings-ansi (0.1.0) test-unit (3.2.8) power_assert + thor (0.20.3) timecop (0.9.1) - unicode-display_width (1.4.0) + tty-color (0.4.3) + tty-pager (0.12.0) + strings (~> 0.1.4) + tty-screen (~> 0.6) + tty-which (~> 0.4) + tty-screen (0.6.5) + tty-tree (0.2.0) + tty-which (0.4.0) + unicode-display_width (1.4.1) + unicode_utils (1.4.0) PLATFORMS ruby DEPENDENCIES + bundler (= 1.16.4) faker! - minitest - rake - rubocop - simplecov - test-unit - timecop + minitest (= 5.11.3) + pry (= 0.12.2) + rake (= 12.3.1) + rubocop (= 0.59.1) + simplecov (= 0.16.1) + test-unit (= 3.2.8) + timecop (= 0.9.1) BUNDLED WITH 1.16.4 diff --git a/bin/faker b/bin/faker new file mode 100755 index 0000000000..4cecb026e6 --- /dev/null +++ b/bin/faker @@ -0,0 +1,19 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +lib_path = File.expand_path('../lib', __dir__) +$LOAD_PATH.unshift(lib_path) unless $LOAD_PATH.include?(lib_path) + +require 'cli' + +Signal.trap('INT') do + warn("\n#{caller.join("\n")}: interrupted") + exit(1) +end + +begin + Faker::CLI::Base.start +rescue Faker::CLI::Base::Error => err + puts "ERROR: #{err.message}" + exit 1 +end diff --git a/faker.gemspec b/faker.gemspec index f98027161f..eb65e4a279 100644 --- a/faker.gemspec +++ b/faker.gemspec @@ -3,26 +3,37 @@ $LOAD_PATH.push File.expand_path('lib', __dir__) require 'faker/version' -Gem::Specification.new do |s| - s.name = 'faker' - s.version = Faker::VERSION - s.platform = Gem::Platform::RUBY - s.authors = ['Benjamin Curtis'] - s.email = ['benjamin.curtis@gmail.com'] - s.homepage = 'https://github.com/stympy/faker' - s.summary = 'Easily generate fake data' - s.description = 'Faker, a port of Data::Faker from Perl, is used to easily generate fake data: names, addresses, phone numbers, etc.' - s.license = 'MIT' +Gem::Specification.new do |spec| + spec.name = 'faker' + spec.version = Faker::VERSION + spec.platform = Gem::Platform::RUBY + spec.authors = ['Benjamin Curtis'] + spec.email = ['benjamin.curtis@gmail.com'] - s.add_runtime_dependency('i18n', '>= 0.7') - s.add_development_dependency('minitest') - s.add_development_dependency('rake') - s.add_development_dependency('rubocop') - s.add_development_dependency('simplecov') - s.add_development_dependency('test-unit') - s.add_development_dependency('timecop') - s.required_ruby_version = '>= 2.3' + spec.summary = 'Easily generate fake data' + spec.description = 'Faker, a port of Data::Faker from Perl, is used to easily generate fake data: names, addresses, phone numbers, etc.' + spec.homepage = 'https://github.com/stympy/faker' + spec.license = 'MIT' - s.files = Dir['lib/**/*'] + %w[History.md License.txt CHANGELOG.md README.md] - s.require_paths = ['lib'] + spec.files = Dir['lib/**/*'] + %w[History.md License.txt CHANGELOG.md README.md] + spec.bindir = 'bin' + spec.executables = ['faker'] + spec.require_paths = ['lib'] + spec.required_ruby_version = '>= 2.3' + + spec.add_dependency('i18n', '>= 0.7') + spec.add_dependency('pastel', '~> 0.7.2') + spec.add_dependency('thor', '~> 0.20.0') + spec.add_dependency('tty-pager', '~> 0.12.0') + spec.add_dependency('tty-screen', '~> 0.6.5') + spec.add_dependency('tty-tree', '~> 0.2.0') + + spec.add_development_dependency('bundler', '1.16.4') + spec.add_development_dependency('minitest', '5.11.3') + spec.add_development_dependency('pry', '0.12.2') + spec.add_development_dependency('rake', '12.3.1') + spec.add_development_dependency('rubocop', '0.59.1') + spec.add_development_dependency('simplecov', '0.16.1') + spec.add_development_dependency('test-unit', '3.2.8') + spec.add_development_dependency('timecop', '0.9.1') end From 38ec79cd8f5fc5c94d8920e82960132360e61531 Mon Sep 17 00:00:00 2001 From: Austin Kabiru Date: Sat, 5 Jan 2019 01:57:50 +0300 Subject: [PATCH 04/15] feat(cli): Add renderer; reflector unit tests --- test/cli/test_reflector.rb | 30 +++++++ test/cli/test_renderer.rb | 158 +++++++++++++++++++++++++++++++++++++ test/test_helper.rb | 1 + 3 files changed, 189 insertions(+) create mode 100644 test/cli/test_reflector.rb create mode 100644 test/cli/test_renderer.rb diff --git a/test/cli/test_reflector.rb b/test/cli/test_reflector.rb new file mode 100644 index 0000000000..134be26b6e --- /dev/null +++ b/test/cli/test_reflector.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +require_relative '../test_helper' + +require 'cli' + +describe Faker::CLI::Reflector do + before do + @reflector = Faker::CLI::Reflector + end + + describe '.find' do + describe 'when a match is found' do + it 'it returns the list of matches' do + result = @reflector.find('firstname') + + assert_kind_of Hash, result + assert_includes result[Faker::Name], :first_name + end + end + + describe 'when no match is found' do + it 'returns an empty array' do + result = @reflector.find('foobar') + + assert_empty result + end + end + end +end diff --git a/test/cli/test_renderer.rb b/test/cli/test_renderer.rb new file mode 100644 index 0000000000..b9a93f26ff --- /dev/null +++ b/test/cli/test_renderer.rb @@ -0,0 +1,158 @@ +# frozen_string_literal: true + +require_relative '../test_helper' + +require 'cli' + +module MockFaker + class Foo + def self.bar + 'bar' + end + end +end + +describe Faker::CLI::Renderer do + before do + @renderer = Faker::CLI::Renderer + end + + describe '#call' do + # TODO: describe 'when paginable object' + + describe 'when non paginable interface' do + it 'renders the full content' do + hash = { MockFaker::Foo => [:bar] } + options = {} + output = StringIO.new + + renderer = @renderer.new(hash, options, output) + renderer.call + + assert_equal "MockFaker::Foo\nā””ā”€ā”€ bar\n", output.string + end + end + end + + describe '#render' do + describe 'when the verbose option is enabled' do + it 'renders methods with data' do + hash = { MockFaker::Foo => [:bar] } + options = { verbose: true } + output = StringIO.new + + renderer = @renderer.new(hash, options, output) + result = renderer.render + + assert_equal "MockFaker::Foo\nā””ā”€ā”€ bar=> bar\n", result + assert_empty output.string + end + end + + describe 'when the verbose option is disabled' do + it 'renders methods only' do + hash = { MockFaker::Foo => [:bar] } + options = { verbose: false } + output = StringIO.new + + renderer = @renderer.new(hash, options, output) + result = renderer.render + + assert_equal "MockFaker::Foo\nā””ā”€ā”€ bar\n", result + assert_empty output.string + end + end + end + + describe '#tree' do + it 'returns the tree object' do + hash = { MockFaker::Foo => [:bar] } + options = {} + output = StringIO.new + + renderer = @renderer.new(hash, options, output) + result = renderer.tree + + assert_equal 2, result.nodes.size + assert_kind_of TTY::Tree, result + assert_empty output.string + end + + it 'memoizes the tree object' do + hash = { MockFaker::Foo => [:bar] } + options = {} + output = StringIO.new + + renderer = @renderer.new(hash, options, output) + first_result = renderer.tree + second_result = renderer.tree + + assert_equal first_result, second_result + end + end + + describe '#gt_screen_height?' do + describe 'when tree size is greater than the screen size' do + it 'returns true' do + hash = { MockFaker::Foo => [:bar] } + options = {} + output = StringIO.new + + TTY::Screen.stub :height, 1 do + renderer = @renderer.new(hash, options, output) + result = renderer.gt_screen_height? + + assert_equal true, result + end + end + end + + describe 'when the tree size is less than the screen size' do + it 'returns false' do + hash = { MockFaker::Foo => [:bar] } + options = {} + output = StringIO.new + + renderer = @renderer.new(hash, options, output) + result = renderer.gt_screen_height? + + assert_equal false, result + end + end + end + + describe '#paginable?' do + describe 'when interactive terminal' do + it 'returns true' do + hash = { MockFaker::Foo => [:bar] } + options = {} + + output_mock = Minitest::Mock.new + + def output_mock.tty? + true + end + + TTY::Screen.stub :height, 1 do + renderer = @renderer.new(hash, options, output_mock) + result = renderer.paginable? + + assert_equal true, result + end + end + end + + describe 'when non-interactive terminal' do + it 'returns false' do + hash = { MockFaker::Foo => [:bar] } + options = {} + output = StringIO.new + + renderer = @renderer.new(hash, options, output) + result = renderer.paginable? + + assert_equal false, result + end + end + end +end diff --git a/test/test_helper.rb b/test/test_helper.rb index 18801ece68..e5cfe30bc7 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -6,6 +6,7 @@ add_filter ['.bundle', 'lib/extensions', 'test'] end +require 'minitest/autorun' require 'test/unit' require 'rubygems' require 'timecop' From c5e7224d292c5ff5c458e47be6d127c115f58b22 Mon Sep 17 00:00:00 2001 From: Austin Kabiru Date: Sat, 5 Jan 2019 02:18:51 +0300 Subject: [PATCH 05/15] feat(cli): Add commands tests --- test/cli/commands/test_list.rb | 37 ++++++++++++++++++++++++++++++++ test/cli/commands/test_search.rb | 36 +++++++++++++++++++++++++++++++ test/cli/test_renderer.rb | 2 +- 3 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 test/cli/commands/test_list.rb create mode 100644 test/cli/commands/test_search.rb diff --git a/test/cli/commands/test_list.rb b/test/cli/commands/test_list.rb new file mode 100644 index 0000000000..224a196cf8 --- /dev/null +++ b/test/cli/commands/test_list.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +require_relative '../../test_helper' + +require 'cli' + +describe Faker::CLI::Commands::List do + before do + @list = Faker::CLI::Commands::List + end + + describe 'when single `list` command' do + it 'executes successfully' do + output = StringIO.new + options = {} + + command = @list.new(options) + command.execute(output: output) + + assert_match(/Faker/, output.string) + assert_equal(true, output.string.lines.size.positive?) + end + end + + describe 'when `list -v` verbose command' do + it 'executes successfully' do + output = StringIO.new + options = { verbose: true } + + command = @list.new(options) + command.execute(output: output) + constant = output.string.lines[0] + + assert_match(/Faker::/, constant) + end + end +end diff --git a/test/cli/commands/test_search.rb b/test/cli/commands/test_search.rb new file mode 100644 index 0000000000..640d75bde3 --- /dev/null +++ b/test/cli/commands/test_search.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +require_relative '../../test_helper' + +require 'cli' + +describe Faker::CLI::Commands::Search do + before do + @search = Faker::CLI::Commands::Search + end + + describe 'when query object exists' do + it 'returns results' do + output = StringIO.new + options = {} + + command = @search.new(options) + command.execute('image', output: output) + + assert_match(/Faker/, output.string) + assert_equal(true, output.string.lines.size.positive?) + end + end + + describe 'when query object does not exist' do + it 'returns nil' do + output = StringIO.new + options = {} + + command = @search.new(options) + command.execute('foobar', output: output) + + assert_empty output.string + end + end +end diff --git a/test/cli/test_renderer.rb b/test/cli/test_renderer.rb index b9a93f26ff..bf44f91e9a 100644 --- a/test/cli/test_renderer.rb +++ b/test/cli/test_renderer.rb @@ -73,7 +73,7 @@ def self.bar renderer = @renderer.new(hash, options, output) result = renderer.tree - assert_equal 2, result.nodes.size + assert_equal true, result.nodes.size.positive? assert_kind_of TTY::Tree, result assert_empty output.string end From 5a650949b9563c4c33b88c9a003cbe4359ead780 Mon Sep 17 00:00:00 2001 From: Austin Kabiru Date: Sat, 5 Jan 2019 02:50:33 +0300 Subject: [PATCH 06/15] feat(cli): Add integration tests --- test/cli/integration/test_list.rb | 37 +++++++++++++++++++++++++ test/cli/integration/test_search.rb | 42 +++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 test/cli/integration/test_list.rb create mode 100644 test/cli/integration/test_search.rb diff --git a/test/cli/integration/test_list.rb b/test/cli/integration/test_list.rb new file mode 100644 index 0000000000..6f1e9329f8 --- /dev/null +++ b/test/cli/integration/test_list.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +require_relative '../../test_helper' + +require 'cli' + +describe '`faker list` command' do + it 'executes `faker help list` command successfully' do + output = `faker help list` + expected_output = <<~OUT + Usage: + faker list + + Options: + -h, [--help], [--no-help] # Display usage information + -m, [--show-methods], [--no-show-methods] # Display Faker constants with methods + # Default: true + -v, [--verbose], [--no-verbose] # Include sample Faker output + + List all Faker constants + OUT + + assert_match(expected_output, output) + end + + it 'executes `faker list` command successfully' do + output = `faker list` + + assert_match(/Faker::/, output) + end + + it 'executes `faker list -v` command successfully' do + output = `faker list -v` + + assert_match(/Faker::/, output) + end +end diff --git a/test/cli/integration/test_search.rb b/test/cli/integration/test_search.rb new file mode 100644 index 0000000000..0b3e1a21de --- /dev/null +++ b/test/cli/integration/test_search.rb @@ -0,0 +1,42 @@ +# frozen_string_literal: true + +require_relative '../../test_helper' + +require 'cli' + +describe '`faker search` command' do + it 'executes `faker help search` command successfully' do + output = `faker help search` + expected_output = <<~OUT + Usage: + faker search [Faker] + + Options: + -h, [--help], [--no-help] # Display usage information + -m, [--show-methods], [--no-show-methods] # Display Faker constants with methods + # Default: true + -v, [--verbose], [--no-verbose] # Include sample Faker output + + Search Faker method(s) + OUT + + assert_match(expected_output, output) + end + + describe 'when search query exists' do + it 'returns results' do + output = `faker search name` + + assert_match(/Faker::/, output) + assert_match(/ā””ā”€ā”€/, output) + end + end + + describe 'when search query does not exist' do + it 'returns a not found message' do + output = `faker search foobar` + + assert_match(/Sorry, we couldn't find a match/, output) + end + end +end From deb31a41de4e1cecae0d078e6072ba18885aa18b Mon Sep 17 00:00:00 2001 From: Austin Kabiru Date: Sat, 5 Jan 2019 03:15:27 +0300 Subject: [PATCH 07/15] =?UTF-8?q?feat(cli):=20Add=20documentation=20?= =?UTF-8?q?=F0=9F=93=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 14 +++++++++--- lib/cli/README.md | 55 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 3 deletions(-) create mode 100644 lib/cli/README.md diff --git a/README.md b/README.md index cd09b5736f..d50b6d0de6 100644 --- a/README.md +++ b/README.md @@ -192,6 +192,14 @@ Faker::Name.name #=> "Christophe Bartell" Faker::Internet.email #=> "kirsten.greenholt@corkeryfisher.info" ``` +### CLI + +Usage Instructions [available here](https://github.com/stympy/faker/blob/master/lib/cli/README.md) + +```bash +$ faker +``` + ### Ensuring unique values Prefix your method call with `unique`. For example: @@ -256,15 +264,15 @@ en-au-ocker: faker: name: # Existing faker field, new data - first_name: + first_name: - Charlotte - Ava - Chloe - Emily # New faker fields - ocker_first_name: - - Bazza + ocker_first_name: + - Bazza - Bluey - Davo - Johno diff --git a/lib/cli/README.md b/lib/cli/README.md new file mode 100644 index 0000000000..627b1ffb99 --- /dev/null +++ b/lib/cli/README.md @@ -0,0 +1,55 @@ +# faker (cli) + +## Usage + +1.) Run a quick lookup + +```bash +$ faker search name +# Faker::SwordArtOnline +# ā””ā”€ā”€ real_name +# ā””ā”€ā”€ game_name +# Faker::Superhero +# ā””ā”€ā”€ name +# .... +``` + +2.) List methods + +```sh +$ faker list +# Faker::BackToTheFuture +# ā”œā”€ā”€ quote +# ā”œā”€ā”€ date +# ā””ā”€ā”€ character +# Faker::Finance +# ā””ā”€ā”€ credit_card +# .... +``` + +`faker` also includes an option to display sample output via the `--verbose` or `-v` flag. :wink: + +3.) + +```sh +$ faker list -v +# Faker::Appliance +# ā”œā”€ā”€ brand=> Whirlpool +# ā””ā”€ā”€ equipment=> Sump pump +# Faker::UmphreysMcgee +# ā””ā”€ā”€ song=> Headphones & Snowcones +$ faker search name -v +# Faker::App +# ā””ā”€ā”€ name=> Subin +# Faker::Address +# ā””ā”€ā”€ street_name=> Percy Landing +# .... +``` + +## Features! :sunglasses: :dancers: + +- [x] List classes with methods E.g. Faker::FunnyName is displayed with `.name`,`.first_name` e.t.c. +- [x] Expand search to Faker::Base sub classes +- [x] Paginate results :book: + +![screenshot 2019-01-05 at 03 02 08](https://user-images.githubusercontent.com/17295175/50717135-59d85780-1096-11e9-8d0d-eca95646644d.jpg) From 96b2dd15274e6db26ccdab5dde8daa23819773e5 Mon Sep 17 00:00:00 2001 From: Austin Kabiru Date: Sat, 5 Jan 2019 03:33:36 +0300 Subject: [PATCH 08/15] chore(cli): Extract constructor to base command --- lib/cli/command.rb | 4 ++++ lib/cli/commands/list.rb | 4 ---- lib/cli/commands/search.rb | 4 ---- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/lib/cli/command.rb b/lib/cli/command.rb index 3140a38462..7fc505b797 100644 --- a/lib/cli/command.rb +++ b/lib/cli/command.rb @@ -13,6 +13,10 @@ class Command def_delegators :command, :run attr_reader :options + def initialize(options) + @options = options + end + def render(result, output) Renderer.call(result, options, output) end diff --git a/lib/cli/commands/list.rb b/lib/cli/commands/list.rb index 9aa42e8ec3..28b811b06e 100644 --- a/lib/cli/commands/list.rb +++ b/lib/cli/commands/list.rb @@ -6,10 +6,6 @@ module Faker module CLI module Commands class List < Faker::CLI::Command - def initialize(options) - @options = options - end - def execute(output: $stdout) result = Faker::CLI::Reflector.list( show_methods: options[:show_methods] diff --git a/lib/cli/commands/search.rb b/lib/cli/commands/search.rb index 27f7cb75aa..de256d4d8a 100644 --- a/lib/cli/commands/search.rb +++ b/lib/cli/commands/search.rb @@ -6,10 +6,6 @@ module Faker module CLI module Commands class Search < Faker::CLI::Command - def initialize(options) - @options = options - end - def execute(input, output: $stdout) result = Faker::CLI::Reflector.find(input) render(result, output) From a4b2bc25401201d238ede3eb51f498fcded33db2 Mon Sep 17 00:00:00 2001 From: Austin Kabiru Date: Sat, 5 Jan 2019 03:37:19 +0300 Subject: [PATCH 09/15] fix(cli): Amend faker version load path - Add integration test to cover that --- lib/cli.rb | 1 - test/cli/integration/test_version.rb | 14 ++++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 test/cli/integration/test_version.rb diff --git a/lib/cli.rb b/lib/cli.rb index a1e595529d..f3496273ee 100644 --- a/lib/cli.rb +++ b/lib/cli.rb @@ -13,7 +13,6 @@ class Base < Thor desc 'version', 'Faker version' def version - require_relative 'version' puts "v#{Faker::VERSION}" end map %w[--version -v] => :version diff --git a/test/cli/integration/test_version.rb b/test/cli/integration/test_version.rb new file mode 100644 index 0000000000..8093458425 --- /dev/null +++ b/test/cli/integration/test_version.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +require_relative '../../test_helper' + +require 'cli' + +describe '`faker version` command' do + it 'executes `faker version` command successfully' do + output = `faker version` + expected_output = 'v1.9.1' + + assert_match(expected_output, output) + end +end From 92850866fb20f0e265da605e8ce0f64262726a78 Mon Sep 17 00:00:00 2001 From: Austin Kabiru Date: Sat, 5 Jan 2019 22:51:36 +0300 Subject: [PATCH 10/15] fix(cli): Skip default deprecation warning output in the CLI --- lib/cli.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/cli.rb b/lib/cli.rb index f3496273ee..b087e0d7a0 100644 --- a/lib/cli.rb +++ b/lib/cli.rb @@ -10,6 +10,8 @@ module Faker module CLI class Base < Thor Error = Class.new(StandardError) + # Skip default deprecation warnings + Gem::Deprecate.skip = true desc 'version', 'Faker version' def version From 63a24f138b5f066e91125bf25f5e136dfbb077ea Mon Sep 17 00:00:00 2001 From: Austin Kabiru Date: Sun, 6 Jan 2019 20:41:52 +0300 Subject: [PATCH 11/15] chore(cli): Amend var names --- lib/cli.rb | 2 +- lib/cli/commands/list.rb | 6 ++---- lib/cli/commands/search.rb | 4 ++-- lib/cli/reflector.rb | 10 +++++----- lib/cli/renderer.rb | 6 +++--- 5 files changed, 13 insertions(+), 15 deletions(-) diff --git a/lib/cli.rb b/lib/cli.rb index b087e0d7a0..21336a576d 100644 --- a/lib/cli.rb +++ b/lib/cli.rb @@ -10,7 +10,7 @@ module Faker module CLI class Base < Thor Error = Class.new(StandardError) - # Skip default deprecation warnings + # Do not print depracation warnings; the CLI will do that Gem::Deprecate.skip = true desc 'version', 'Faker version' diff --git a/lib/cli/commands/list.rb b/lib/cli/commands/list.rb index 28b811b06e..e77965dc74 100644 --- a/lib/cli/commands/list.rb +++ b/lib/cli/commands/list.rb @@ -5,11 +5,9 @@ module Faker module CLI module Commands - class List < Faker::CLI::Command + class List < Command def execute(output: $stdout) - result = Faker::CLI::Reflector.list( - show_methods: options[:show_methods] - ) + result = Reflector.list(show_methods: options[:show_methods]) render(result, output) end end diff --git a/lib/cli/commands/search.rb b/lib/cli/commands/search.rb index de256d4d8a..cf91397588 100644 --- a/lib/cli/commands/search.rb +++ b/lib/cli/commands/search.rb @@ -5,9 +5,9 @@ module Faker module CLI module Commands - class Search < Faker::CLI::Command + class Search < Command def execute(input, output: $stdout) - result = Faker::CLI::Reflector.find(input) + result = Reflector.find(input) render(result, output) end diff --git a/lib/cli/reflector.rb b/lib/cli/reflector.rb index 2af3bdea13..0938483eb6 100644 --- a/lib/cli/reflector.rb +++ b/lib/cli/reflector.rb @@ -52,17 +52,17 @@ def list(show_methods) private def all_descendants_with_methods - faker_descendants.each do |faker| - store(faker, faker.my_singleton_methods) + faker_descendants.each do |descendant| + store(descendant, descendant.my_singleton_methods) end descendants_with_methods end def search_descendants_matching_query - faker_descendants.each do |faker| - methods = faker.my_singleton_methods + faker_descendants.each do |descendant| + methods = descendant.my_singleton_methods matching = methods.select { |m| query_matches?(m.to_s) } - store(faker, matching) + store(descendant, matching) end end diff --git a/lib/cli/renderer.rb b/lib/cli/renderer.rb index 12850949f1..0e3f635067 100644 --- a/lib/cli/renderer.rb +++ b/lib/cli/renderer.rb @@ -49,11 +49,11 @@ def gt_screen_height? private def build_tree - result = hash.reduce({}) do |h, (faker, methods)| - h.merge! node(faker, methods&.sort) + results = hash.reduce({}) do |h, (const, methods)| + h.merge! node(const, methods&.sort) end - result.sort_by(&:to_s).to_h + results.sort_by(&:to_s).to_h end def node(const, methods) From fd9d9862038614825817ebd941b8a210d9ba473f Mon Sep 17 00:00:00 2001 From: Austin Kabiru Date: Tue, 22 Jan 2019 10:16:03 +0300 Subject: [PATCH 12/15] chore(reflectors): Distribute Reflector responsibilities The Reflector was doing too much; handling Search and List reflections which made it a tad harder to follow. This commit defines a Reflection interface and the correspoding subclasses. --- lib/cli/command.rb | 1 - lib/cli/commands/list.rb | 3 +- lib/cli/commands/search.rb | 9 +++--- lib/cli/reflector.rb | 51 ++++-------------------------- lib/cli/reflectors/list.rb | 39 +++++++++++++++++++++++ lib/cli/reflectors/search.rb | 46 +++++++++++++++++++++++++++ test/cli/commands/test_search.rb | 4 +-- test/cli/reflectors/test_list.rb | 46 +++++++++++++++++++++++++++ test/cli/reflectors/test_search.rb | 37 ++++++++++++++++++++++ test/cli/test_reflector.rb | 30 ------------------ 10 files changed, 184 insertions(+), 82 deletions(-) create mode 100644 lib/cli/reflectors/list.rb create mode 100644 lib/cli/reflectors/search.rb create mode 100644 test/cli/reflectors/test_list.rb create mode 100644 test/cli/reflectors/test_search.rb delete mode 100644 test/cli/test_reflector.rb diff --git a/lib/cli/command.rb b/lib/cli/command.rb index 7fc505b797..277e7a12e2 100644 --- a/lib/cli/command.rb +++ b/lib/cli/command.rb @@ -2,7 +2,6 @@ require 'forwardable' -require_relative 'reflector' require_relative 'renderer' module Faker diff --git a/lib/cli/commands/list.rb b/lib/cli/commands/list.rb index e77965dc74..060c88db77 100644 --- a/lib/cli/commands/list.rb +++ b/lib/cli/commands/list.rb @@ -1,13 +1,14 @@ # frozen_string_literal: true require_relative '../command' +require_relative '../reflectors/list' module Faker module CLI module Commands class List < Command def execute(output: $stdout) - result = Reflector.list(show_methods: options[:show_methods]) + result = Reflectors::List.call(options) render(result, output) end end diff --git a/lib/cli/commands/search.rb b/lib/cli/commands/search.rb index cf91397588..ec04ecc73a 100644 --- a/lib/cli/commands/search.rb +++ b/lib/cli/commands/search.rb @@ -1,26 +1,27 @@ # frozen_string_literal: true require_relative '../command' +require_relative '../reflectors/search' module Faker module CLI module Commands class Search < Command def execute(input, output: $stdout) - result = Reflector.find(input) + result = Reflectors::Search.call(input) render(result, output) end private def render(result, output) - return not_found if result.empty? + return not_found(output) if result.empty? super(result, output) end - def not_found - puts "\nSorry, we couldn't find a match šŸ˜¢", "\n" + def not_found(output) + output.puts "\nSorry, we couldn't find a match šŸ˜¢", "\n" end end end diff --git a/lib/cli/reflector.rb b/lib/cli/reflector.rb index 0938483eb6..7ff45b35a1 100644 --- a/lib/cli/reflector.rb +++ b/lib/cli/reflector.rb @@ -4,8 +4,11 @@ module Faker module CLI - # Exposes `Faker` reflection methods + # Abstract `Faker` Reflector - introspects the `Faker` module + # # @api private + # @abstract + # class Reflector Faker::Base.class_eval do # Select `Faker` subclasses @@ -23,53 +26,13 @@ def self.my_singleton_methods end end - attr_reader :descendants_with_methods, :query + attr_reader :descendants_with_methods - def initialize(query = nil) + def initialize(*) @descendants_with_methods = Hash.new { |h, k| h[k] = [] } - @query = query end - class << self - def find(query) - new(query).find - end - - def list(show_methods: false) - new.list(show_methods) - end - end - - def find - search_descendants_matching_query - descendants_with_methods - end - - def list(show_methods) - show_methods ? all_descendants_with_methods : faker_descendants - end - - private - - def all_descendants_with_methods - faker_descendants.each do |descendant| - store(descendant, descendant.my_singleton_methods) - end - descendants_with_methods - end - - def search_descendants_matching_query - faker_descendants.each do |descendant| - methods = descendant.my_singleton_methods - matching = methods.select { |m| query_matches?(m.to_s) } - store(descendant, matching) - end - end - - def query_matches?(method_name) - method_name_parts = method_name.split(/_/).reject(&:empty?) - query.match(/#{method_name_parts.join('|')}/) - end + protected def store(descendant, methods) return if methods.empty? diff --git a/lib/cli/reflectors/list.rb b/lib/cli/reflectors/list.rb new file mode 100644 index 0000000000..719188b3bc --- /dev/null +++ b/lib/cli/reflectors/list.rb @@ -0,0 +1,39 @@ +# frozen_string_literal: true + +require_relative '../reflector' + +module Faker + module CLI + module Reflectors + # List command reflector + # @api private + # + class List < Reflector + attr_reader :show_methods + + def self.call(options) + new(options).call + end + + def initialize(options = {}) + @show_methods = options[:show_methods] + + super + end + + def call + show_methods ? all_descendants_with_methods : faker_descendants + end + + private + + def all_descendants_with_methods + faker_descendants.each do |descendant| + store(descendant, descendant.my_singleton_methods) + end + descendants_with_methods + end + end + end + end +end diff --git a/lib/cli/reflectors/search.rb b/lib/cli/reflectors/search.rb new file mode 100644 index 0000000000..48e88a0276 --- /dev/null +++ b/lib/cli/reflectors/search.rb @@ -0,0 +1,46 @@ +# frozen_string_literal: true + +require_relative '../reflector' + +module Faker + module CLI + module Reflectors + # Find command reflector + # @api private + # + class Search < Reflector + attr_reader :query + + def self.call(query) + new(query).call + end + + def initialize(query) + @query = query + + super + end + + def call + search_descendants_matching_query + descendants_with_methods + end + + private + + def search_descendants_matching_query + faker_descendants.each do |descendant| + methods = descendant.my_singleton_methods + matching = methods.select { |method| query_matches?(method.to_s) } + store(descendant, matching) + end + end + + def query_matches?(method_name) + method_name_parts = method_name.split(/_/).reject(&:empty?) + query.match(/#{method_name_parts.join('|')}/) + end + end + end + end +end diff --git a/test/cli/commands/test_search.rb b/test/cli/commands/test_search.rb index 640d75bde3..89a22fd326 100644 --- a/test/cli/commands/test_search.rb +++ b/test/cli/commands/test_search.rb @@ -23,14 +23,14 @@ end describe 'when query object does not exist' do - it 'returns nil' do + it 'returns a not found message' do output = StringIO.new options = {} command = @search.new(options) command.execute('foobar', output: output) - assert_empty output.string + assert_match(/Sorry, we couldn't find a match/, output.string) end end end diff --git a/test/cli/reflectors/test_list.rb b/test/cli/reflectors/test_list.rb new file mode 100644 index 0000000000..4e33ea3e14 --- /dev/null +++ b/test/cli/reflectors/test_list.rb @@ -0,0 +1,46 @@ +# frozen_string_literal: true + +require_relative '../../test_helper' + +require 'cli' + +describe Faker::CLI::Reflectors::List do + before do + @reflector = Faker::CLI::Reflectors::List + end + + describe '#call' do + describe 'when show methods is enabled' do + it 'returns all descendants and their methods' do + options = { show_methods: true } + + reflector = @reflector.new(options) + result = reflector.call + + sample_result = result.first + sample_result_key = sample_result.first.to_s + sample_result_value = sample_result.last + + assert_kind_of(Hash, result) + assert_match(/Faker::/, sample_result_key) + assert_kind_of(Array, sample_result_value) + refute_empty(sample_result_value) + end + end + + describe 'when show methods is disabled' do + it 'returns only the descendants' do + options = { show_methods: false } + + reflector = @reflector.new(options) + result = reflector.call + + sample_result = result.first.to_s + + assert_kind_of(Array, result) + assert_match(/Faker::/, sample_result) + refute_empty(result) + end + end + end +end diff --git a/test/cli/reflectors/test_search.rb b/test/cli/reflectors/test_search.rb new file mode 100644 index 0000000000..d83f277f8e --- /dev/null +++ b/test/cli/reflectors/test_search.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +require_relative '../../test_helper' + +require 'cli' + +describe Faker::CLI::Reflectors::Search do + before do + @reflector = Faker::CLI::Reflectors::Search + end + + describe '#call' do + describe 'when a match is found' do + it 'it returns the list of matches' do + query = 'firstname' + + reflector = @reflector.new(query) + result = reflector.call + + assert_includes(result[Faker::Name], :first_name) + assert_kind_of(Hash, result) + end + end + + describe 'when no match is found' do + it 'returns an empty hash' do + query = 'foobar' + + reflector = @reflector.new(query) + result = reflector.call + + assert_empty(result) + assert_kind_of(Hash, result) + end + end + end +end diff --git a/test/cli/test_reflector.rb b/test/cli/test_reflector.rb deleted file mode 100644 index 134be26b6e..0000000000 --- a/test/cli/test_reflector.rb +++ /dev/null @@ -1,30 +0,0 @@ -# frozen_string_literal: true - -require_relative '../test_helper' - -require 'cli' - -describe Faker::CLI::Reflector do - before do - @reflector = Faker::CLI::Reflector - end - - describe '.find' do - describe 'when a match is found' do - it 'it returns the list of matches' do - result = @reflector.find('firstname') - - assert_kind_of Hash, result - assert_includes result[Faker::Name], :first_name - end - end - - describe 'when no match is found' do - it 'returns an empty array' do - result = @reflector.find('foobar') - - assert_empty result - end - end - end -end From a80062191d02d1903ad24f06b423a011de82a903 Mon Sep 17 00:00:00 2001 From: Austin Kabiru Date: Fri, 15 Feb 2019 09:55:24 +0300 Subject: [PATCH 13/15] chore: Don't specify bunlder version There's an erroneous 'null byte' error in the CI which could be caused by the bundler version. Further, As of Ruby 2.6.0, bundler is now built into Ruby, so no need to install it ourselves --- Gemfile.lock | 3 +-- faker.gemspec | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 5f135df524..b0306361a1 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -74,7 +74,6 @@ PLATFORMS ruby DEPENDENCIES - bundler (= 1.16.4) faker! minitest (= 5.11.3) pry (= 0.12.2) @@ -85,4 +84,4 @@ DEPENDENCIES timecop (= 0.9.1) BUNDLED WITH - 1.17.1 + 1.17.3 diff --git a/faker.gemspec b/faker.gemspec index b37b1f0c81..98d5e87338 100644 --- a/faker.gemspec +++ b/faker.gemspec @@ -32,7 +32,6 @@ Gem::Specification.new do |spec| spec.add_dependency('tty-screen', '~> 0.6.5') spec.add_dependency('tty-tree', '~> 0.2.0') - spec.add_development_dependency('bundler', '1.16.4') spec.add_development_dependency('minitest', '5.11.3') spec.add_development_dependency('pry', '0.12.2') spec.add_development_dependency('rake', '12.3.1') From 7ca6e5db2e0e18d939bfcea40ab1eaddfeb1de6a Mon Sep 17 00:00:00 2001 From: Austin Kabiru Date: Mon, 18 Feb 2019 02:03:00 +0300 Subject: [PATCH 14/15] chore: Address review comments * move cli doc to unreleased * Reinstate rubygems deprecation warnings --- README.md | 8 -------- lib/cli.rb | 5 ++++- unreleased_README.md | 14 +++++++++++--- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 1ef3752035..687201df4e 100644 --- a/README.md +++ b/README.md @@ -62,14 +62,6 @@ Faker::Name.name #=> "Christophe Bartell" Faker::Internet.email #=> "kirsten.greenholt@corkeryfisher.info" ``` -### CLI - -Usage Instructions [available here](https://github.com/stympy/faker/blob/master/lib/cli/README.md) - -```bash -$ faker -``` - ### Ensuring unique values Prefix your method call with `unique`. For example: ```ruby diff --git a/lib/cli.rb b/lib/cli.rb index 21336a576d..ccb47d72d0 100644 --- a/lib/cli.rb +++ b/lib/cli.rb @@ -10,7 +10,7 @@ module Faker module CLI class Base < Thor Error = Class.new(StandardError) - # Do not print depracation warnings; the CLI will do that + # Tempararily disable default deprecation warnings Gem::Deprecate.skip = true desc 'version', 'Faker version' @@ -48,6 +48,9 @@ def search(query) Faker::CLI::Commands::Search.new(options).execute(query) end end + + # Reinstate default deprecation warnings + Gem::Deprecate.skip = false end end end diff --git a/unreleased_README.md b/unreleased_README.md index 6693ae9f38..bb20198c6e 100644 --- a/unreleased_README.md +++ b/unreleased_README.md @@ -64,6 +64,14 @@ Faker::Name.name #=> "Christophe Bartell" Faker::Internet.email #=> "kirsten.greenholt@corkeryfisher.info" ``` +### CLI + +Usage Instructions [available here](https://github.com/stympy/faker/blob/master/lib/cli/README.md) + +```bash +$ faker +``` + ### Ensuring unique values Prefix your method call with `unique`. For example: ```ruby @@ -321,15 +329,15 @@ en-au-ocker: faker: name: # Existing faker field, new data - first_name: + first_name: - Charlotte - Ava - Chloe - Emily # New faker fields - ocker_first_name: - - Bazza + ocker_first_name: + - Bazza - Bluey - Davo - Johno From 491b63aede1647f039e686f3608a46140b5134a1 Mon Sep 17 00:00:00 2001 From: Austin Kabiru Date: Mon, 18 Feb 2019 21:46:32 +0300 Subject: [PATCH 15/15] chore: Skip Gem::Deprecate warning output in CLI --- lib/cli.rb | 69 ++++++++++++++++++++++++++---------------------------- 1 file changed, 33 insertions(+), 36 deletions(-) diff --git a/lib/cli.rb b/lib/cli.rb index ccb47d72d0..5b87554494 100644 --- a/lib/cli.rb +++ b/lib/cli.rb @@ -10,47 +10,44 @@ module Faker module CLI class Base < Thor Error = Class.new(StandardError) - # Tempararily disable default deprecation warnings - Gem::Deprecate.skip = true - - desc 'version', 'Faker version' - def version - puts "v#{Faker::VERSION}" - end - map %w[--version -v] => :version + # Skip default deprecation warning output; the CLI will display that. + Gem::Deprecate.skip_during do + desc 'version', 'Faker version' + def version + puts "v#{Faker::VERSION}" + end + map %w[--version -v] => :version - desc 'list', 'List all Faker constants' - method_option :help, aliases: '-h', type: :boolean, - desc: 'Display usage information' - method_option :show_methods, aliases: '-m', type: :boolean, default: true, - desc: 'Display Faker constants with methods' - method_option :verbose, aliases: '-v', type: :boolean, - desc: 'Include sample Faker output' - def list(*) - if options[:help] - invoke :help, ['list'] - else - Faker::CLI::Commands::List.new(options).execute + desc 'list', 'List all Faker constants' + method_option :help, aliases: '-h', type: :boolean, + desc: 'Display usage information' + method_option :show_methods, aliases: '-m', type: :boolean, default: true, + desc: 'Display Faker constants with methods' + method_option :verbose, aliases: '-v', type: :boolean, + desc: 'Include sample Faker output' + def list(*) + if options[:help] + invoke :help, ['list'] + else + Faker::CLI::Commands::List.new(options).execute + end end - end - desc 'search [Faker]', 'Search Faker method(s)' - method_option :help, aliases: '-h', type: :boolean, - desc: 'Display usage information' - method_option :show_methods, aliases: '-m', type: :boolean, default: true, - desc: 'Display Faker constants with methods' - method_option :verbose, aliases: '-v', type: :boolean, - desc: 'Include sample Faker output' - def search(query) - if options[:help] - invoke :help, ['search'] - else - Faker::CLI::Commands::Search.new(options).execute(query) + desc 'search [Faker]', 'Search Faker method(s)' + method_option :help, aliases: '-h', type: :boolean, + desc: 'Display usage information' + method_option :show_methods, aliases: '-m', type: :boolean, default: true, + desc: 'Display Faker constants with methods' + method_option :verbose, aliases: '-v', type: :boolean, + desc: 'Include sample Faker output' + def search(query) + if options[:help] + invoke :help, ['search'] + else + Faker::CLI::Commands::Search.new(options).execute(query) + end end end - - # Reinstate default deprecation warnings - Gem::Deprecate.skip = false end end end