diff --git a/Gemfile.lock b/Gemfile.lock index 8cbcaa17a0..b0306361a1 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -3,26 +3,40 @@ PATH specs: faker (1.9.3) 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) + coderay (1.1.2) concurrent-ruby (1.1.4) docile (1.3.1) - i18n (1.5.3) + 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,38 @@ 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 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.17.1 + 1.17.3 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 fd2972314b..98d5e87338 100644 --- a/faker.gemspec +++ b/faker.gemspec @@ -3,30 +3,40 @@ $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' - s.metadata['changelog_uri'] = 'https://github.com/stympy/faker/blob/master/CHANGELOG.md' - s.metadata['source_code_uri'] = 'https://github.com/stympy/faker' - s.metadata['bug_tracker_uri'] = 'https://github.com/stympy/faker/issues' + spec.metadata['changelog_uri'] = 'https://github.com/stympy/faker/blob/master/CHANGELOG.md' + spec.metadata['source_code_uri'] = 'https://github.com/stympy/faker' + spec.metadata['bug_tracker_uri'] = 'https://github.com/stympy/faker/issues' + + 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('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 diff --git a/lib/cli.rb b/lib/cli.rb new file mode 100644 index 0000000000..5b87554494 --- /dev/null +++ b/lib/cli.rb @@ -0,0 +1,53 @@ +# frozen_string_literal: true + +require 'thor' + +require 'cli/commands/list' +require 'cli/commands/search' +require 'faker/version' + +module Faker + module CLI + class Base < Thor + Error = Class.new(StandardError) + # 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 + 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 +end 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) diff --git a/lib/cli/command.rb b/lib/cli/command.rb new file mode 100644 index 0000000000..277e7a12e2 --- /dev/null +++ b/lib/cli/command.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +require 'forwardable' + +require_relative 'renderer' + +module Faker + module CLI + class Command + extend Forwardable + + def_delegators :command, :run + attr_reader :options + + def initialize(options) + @options = options + end + + def render(result, output) + Renderer.call(result, options, output) + end + end + end +end diff --git a/lib/cli/commands/list.rb b/lib/cli/commands/list.rb new file mode 100644 index 0000000000..060c88db77 --- /dev/null +++ b/lib/cli/commands/list.rb @@ -0,0 +1,17 @@ +# 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 = Reflectors::List.call(options) + render(result, output) + end + end + end + end +end diff --git a/lib/cli/commands/search.rb b/lib/cli/commands/search.rb new file mode 100644 index 0000000000..ec04ecc73a --- /dev/null +++ b/lib/cli/commands/search.rb @@ -0,0 +1,29 @@ +# 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 = Reflectors::Search.call(input) + render(result, output) + end + + private + + def render(result, output) + return not_found(output) if result.empty? + + super(result, output) + end + + def not_found(output) + output.puts "\nSorry, we couldn't find a match 😢", "\n" + end + end + end + end +end diff --git a/lib/cli/reflector.rb b/lib/cli/reflector.rb new file mode 100644 index 0000000000..7ff45b35a1 --- /dev/null +++ b/lib/cli/reflector.rb @@ -0,0 +1,48 @@ +# frozen_string_literal: true + +require 'faker' + +module Faker + module CLI + # Abstract `Faker` Reflector - introspects the `Faker` module + # + # @api private + # @abstract + # + 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 + + def initialize(*) + @descendants_with_methods = Hash.new { |h, k| h[k] = [] } + end + + protected + + 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/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/lib/cli/renderer.rb b/lib/cli/renderer.rb new file mode 100644 index 0000000000..0e3f635067 --- /dev/null +++ b/lib/cli/renderer.rb @@ -0,0 +1,93 @@ +# frozen_string_literal: true + +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 + @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 + results = hash.reduce({}) do |h, (const, methods)| + h.merge! node(const, methods&.sort) + end + + results.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] + 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 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..89a22fd326 --- /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 a not found message' do + output = StringIO.new + options = {} + + command = @search.new(options) + command.execute('foobar', output: output) + + assert_match(/Sorry, we couldn't find a match/, output.string) + end + end +end 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 diff --git a/test/cli/integration/test_version.rb b/test/cli/integration/test_version.rb new file mode 100644 index 0000000000..722a7e9fcc --- /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.3' + + assert_match(expected_output, output) + 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_renderer.rb b/test/cli/test_renderer.rb new file mode 100644 index 0000000000..bf44f91e9a --- /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 true, result.nodes.size.positive? + 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_determinism.rb b/test/test_determinism.rb index da70b1e510..77c834cf47 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 Sports 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 Sports SwordArtOnline TvShows Time VERSION Witcher WorldOfWarcraft Zelda].include?(subclass) end.sort 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' diff --git a/unreleased_README.md b/unreleased_README.md index 58783f6caf..fe402738af 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