Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add fakerbot list Command #2

Merged
merged 4 commits into from
Aug 10, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
fakerbot (0.2.4)
fakerbot (0.3.0)
faker
pastel (~> 0.7.2)
thor (~> 0.20.0)
Expand Down
31 changes: 23 additions & 8 deletions lib/fakerbot/bot.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,37 +20,52 @@ def self.my_singleton_methods
end
end

attr_reader :matching_descendants, :query
attr_reader :descendants_with_methods, :query

def initialize(query)
@matching_descendants = Hash.new { |h, k| h[k] = [] }
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(verbose: false)
new.list(verbose)
end
end

def find
search_descendants_matching_query
matching_descendants
descendants_with_methods
end

def list(verbose)
verbose ? 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| m.match?(/#{query}/i) }
save_matching(faker, matching)
store(faker, matching)
end
end

def save_matching(descendant, matching)
return if matching.empty?
matching_descendants[descendant].concat(matching)
def store(descendant, methods)
return if methods.empty?
descendants_with_methods[descendant].concat(methods)
end

def faker_descendants
Expand Down
16 changes: 15 additions & 1 deletion lib/fakerbot/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
require 'thor'
require 'fakerbot/cli'
require 'fakerbot/version'
require 'fakerbot/commands/list'
require 'fakerbot/commands/search'

module FakerBot
Expand All @@ -16,11 +17,24 @@ def 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 :verbose, aliases: '-v', type: :boolean,
desc: 'Display Faker constants with methods'
def list(*)
if options[:help]
invoke :help, ['list']
else
FakerBot::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 :verbose, aliases: '-v', type: :boolean,
desc: 'Display Faker classes with methods'
desc: 'Display Faker constants methods with examples'
def search(query)
if options[:help]
invoke :help, ['search']
Expand Down
43 changes: 43 additions & 0 deletions lib/fakerbot/command.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# frozen_string_literal: true

require 'forwardable'
require 'pastel'
require 'tty/pager'
require 'tty/tree'

module FakerBot
class Command
extend Forwardable

def_delegators :command, :run

def pager
TTY::Pager.new(command: 'less -R')
end

def screen
TTY::Screen
end

def tree(input)
TTY::Tree.new do
input.each do |faker, methods|
node Pastel.new.green(faker.to_s) do
methods&.each { |m| leaf Pastel.new.cyan(m.to_s) }
end
end
end
end

def render(result, output = $stdout)
result_tree = tree(result)
view = result_tree.render
if screen.height < result_tree.nodes.size
# paginate when attached to terminal
output.tty? ? pager.page(view) : output.puts(view)
else
output.puts view
end
end
end
end
17 changes: 17 additions & 0 deletions lib/fakerbot/commands/list.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# frozen_string_literal: true

require_relative '../command'

module FakerBot
module Commands
class List < FakerBot::Command
def initialize(options)
@options = options
end

def execute(output: $stdout)
render FakerBot::Bot.list(verbose: @options[:verbose]), output
end
end
end
end
33 changes: 6 additions & 27 deletions lib/fakerbot/commands/search.rb
Original file line number Diff line number Diff line change
@@ -1,45 +1,24 @@
# frozen_string_literal: true

require 'pastel'
require 'tty/pager'
require 'tty/tree'
require 'fakerbot/bot'
require_relative '../command'

module FakerBot
module Commands
class Search
class Search < FakerBot::Command
def initialize(options)
@options = options
@pager = TTY::Pager.new(command: 'less -R')
@screen = TTY::Screen
end

def execute(input)
render FakerBot::Bot.find(input)
def execute(input, output: $stdout)
render FakerBot::Bot.find(input), output
end

private

attr_reader :screen, :pager

def render(result)
def render(result, output)
return not_found if result.empty?
output = tree(result)
if screen.height < output.nodes.size
pager.page output.render
else
puts output.render
end
end

def tree(input)
TTY::Tree.new do
input.each do |faker, methods|
node Pastel.new.green(faker.to_s) do
methods.each { |m| leaf Pastel.new.cyan(m.to_s) }
end
end
end
super(result, output)
end

def not_found
Expand Down
1 change: 1 addition & 0 deletions lib/fakerbot/templates/list/.gitkeep
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#
2 changes: 1 addition & 1 deletion lib/fakerbot/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module FakerBot
VERSION = '0.2.4'.freeze
VERSION = '0.3.0'.freeze
end
30 changes: 30 additions & 0 deletions spec/integration/list_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# frozen_string_literal: true

RSpec.describe '`fakerbot list` command', type: :cli do
it 'executes `fakerbot help list` command successfully' do
output = `fakerbot help list`
expected_output = <<~OUT
Usage:
fakerbot list

Options:
-h, [--help], [--no-help] # Display usage information
-v, [--verbose], [--no-verbose] # Display Faker constants with methods

List all Faker constants
OUT

expect(output).to eq(expected_output)
end

it 'executes `fakerbot list` command successfully' do
output = `fakerbot list`
expect(output).to match(/Faker::/)
end

it 'executes `fakerbot list -v` command successfully' do
output = `fakerbot list -v`
expect(output).to match(/Faker::/)
expect(output).to match(/└──/)
end
end
34 changes: 34 additions & 0 deletions spec/integration/search_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# frozen_string_literal: true

RSpec.describe '`fakerbot search` command', type: :cli do
it 'executes `fakerbot help search` command successfully' do
output = `fakerbot help search`
expected_output = <<~OUT
Usage:
fakerbot search [Faker]

Options:
-h, [--help], [--no-help] # Display usage information
-v, [--verbose], [--no-verbose] # Display Faker constants methods with examples

Search Faker method(s)
OUT

expect(output).to eq(expected_output)
end

context 'when search query exists' do
it 'returns results' do
output = `fakerbot search name`
expect(output).to match(/Faker::/)
expect(output).to match(/└──/)
end
end

context 'when search query does not exist' do
it 'returns a not found message' do
output = `fakerbot search asdasdhk`
expect(output).to match(/Sorry, we couldn't find a match/)
end
end
end
31 changes: 31 additions & 0 deletions spec/unit/list_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
require 'fakerbot/commands/list'

RSpec.describe FakerBot::Commands::List do
let(:output) { StringIO.new }
let(:options) { {} }
let(:command) { FakerBot::Commands::List.new(options) }

before do
command.execute(output: output)
end

context 'when single `list` command' do
it 'executes successfully' do
expect(output.string).to match(/Faker/)
expect(output.string.lines.size).to be_positive
end
end

context 'when `list -v` verbose command' do
let(:options) { { verbose: true } }

it 'executes successfully' do
constant = output.string.lines[0]
method = output.string.lines[1]

expect(constant).to match(/Faker::/)
expect(method).not_to match(/Faker::/)
expect(method).to match(/└──/)
end
end
end
28 changes: 28 additions & 0 deletions spec/unit/search_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
require 'fakerbot/commands/search'

RSpec.describe FakerBot::Commands::Search do
let(:output) { StringIO.new }
let(:options) { {} }
let(:command) { described_class.new(options) }

context 'when query object exists' do
before do
command.execute('image', output: output)
end

it 'returns results' do
expect(output.string).to match(/Faker/)
expect(output.string.lines.size).to be_positive
end
end

context 'when query object does not exist' do
before do
command.execute('hasjdhaksjd', output: output)
end

it 'returns nil' do
expect(output.string).to be_empty
end
end
end