ki_trello 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +19 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +29 -0
- data/Rakefile +23 -0
- data/bin/ki_trello +86 -0
- data/ki_trello.gemspec +32 -0
- data/lib/ki_trello/command.rb +66 -0
- data/lib/ki_trello/interactive.rb +96 -0
- data/lib/ki_trello/kiseru.rb +74 -0
- data/lib/ki_trello/session.rb +87 -0
- data/lib/ki_trello/version.rb +3 -0
- data/lib/ki_trello.rb +15 -0
- data/spec/integration/command_spec.rb +92 -0
- data/spec/spec_helper.rb +40 -0
- metadata +207 -0
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Ben Brinckerhoff
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# KiTrello
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'ki_trello'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install ki_trello
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
require "bundler/gem_tasks"
|
3
|
+
require 'rspec/core/rake_task'
|
4
|
+
|
5
|
+
desc 'Default: run specs.'
|
6
|
+
task :default => :spec
|
7
|
+
|
8
|
+
desc "Run specs"
|
9
|
+
RSpec::Core::RakeTask.new do |t|
|
10
|
+
t.pattern = "./spec/**/*_spec.rb"
|
11
|
+
end
|
12
|
+
|
13
|
+
desc "Generate code coverage"
|
14
|
+
RSpec::Core::RakeTask.new("spec:coverage") do |t|
|
15
|
+
ENV['COVERAGE'] = "true"
|
16
|
+
end
|
17
|
+
|
18
|
+
desc "Delete *all* VCR cassettes (!)"
|
19
|
+
namespace :spec do
|
20
|
+
task :vcr_wipe do
|
21
|
+
FileUtils.rm_rf('spec/fixtures/vcr_cassettes')
|
22
|
+
end
|
23
|
+
end
|
data/bin/ki_trello
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# 1.9 adds realpath to resolve symlinks; 1.8 doesn't
|
3
|
+
# have this method, so we add it so we get resolved symlinks
|
4
|
+
# and compatibility
|
5
|
+
unless File.respond_to? :realpath
|
6
|
+
class File #:nodoc:
|
7
|
+
def self.realpath path
|
8
|
+
return realpath(File.readlink(path)) if symlink?(path)
|
9
|
+
path
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
$LOAD_PATH << File.expand_path(File.dirname(File.realpath(__FILE__)) + '/../lib')
|
15
|
+
|
16
|
+
require 'rubygems'
|
17
|
+
require 'gli'
|
18
|
+
require 'ki_trello'
|
19
|
+
require 'colored'
|
20
|
+
include GLI
|
21
|
+
|
22
|
+
program_desc 'A Kiseru client for Trello'
|
23
|
+
|
24
|
+
version KiTrello::VERSION
|
25
|
+
|
26
|
+
desc 'Initialise config files'
|
27
|
+
command :init do |c|
|
28
|
+
c.action do |global_options,options,args|
|
29
|
+
config = Kiseru::Config[:ki_trello]
|
30
|
+
config.write('username', KiTrello::Interactive.repeatedly_ask("Username: "))
|
31
|
+
config.write('developer_api_key', KiTrello::Interactive.repeatedly_ask("Please enter your Trello Developer API key.\n Generate a developer key by logging into Trello and visiting https://trello.com/1/appKey/generate.\n Key"))
|
32
|
+
key = config.read('developer_api_key')
|
33
|
+
config.write('member_token', KiTrello::Interactive.repeatedly_ask("Please enter your member token. You can retrieve it by visiting https://trello.com/1/authorize?key=#{key}&name=ki_trello&expiration=30days&response_type=token&scope=read,write
|
34
|
+
\n
|
35
|
+
.\n Token"))
|
36
|
+
$stdout.puts "Initialized config file at #{config.path}".green
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
desc 'List boards'
|
41
|
+
command :boards do |c|
|
42
|
+
c.action do |global_options, options, args|
|
43
|
+
command = KiTrello::Command.new
|
44
|
+
command.list_boards
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
desc 'Get card by ID (or short URL)'
|
49
|
+
command :card do |c|
|
50
|
+
c.action do |global_options, options, args|
|
51
|
+
card_id = args.first
|
52
|
+
command = KiTrello::Command.new
|
53
|
+
command.get_card(card_id)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
desc 'Create new card'
|
58
|
+
command :new_card do |c|
|
59
|
+
c.desc "The list ID"
|
60
|
+
c.flag [:list]
|
61
|
+
c.action do |global_options, options, args|
|
62
|
+
list_id = options[:list]
|
63
|
+
command = KiTrello::Command.new
|
64
|
+
command.create_card(:list => list_id)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
desc 'List lists in board'
|
69
|
+
command :lists do |c|
|
70
|
+
c.desc "The board ID"
|
71
|
+
c.flag [:board]
|
72
|
+
c.desc "Interactive Mode"
|
73
|
+
c.switch [:i]
|
74
|
+
c.action do |global_options, options, args|
|
75
|
+
unless board_id = options[:board]
|
76
|
+
if options[:i]
|
77
|
+
board_id = KiTrello::Interactive.select_board("\n Which board would you like to view?")
|
78
|
+
else
|
79
|
+
end
|
80
|
+
end
|
81
|
+
command = KiTrello::Command.new
|
82
|
+
command.list_lists(board_id)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
exit GLI.run(ARGV)
|
data/ki_trello.gemspec
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/ki_trello/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Ben Brinckerhoff"]
|
6
|
+
gem.email = ["ben@freeagent.com"]
|
7
|
+
gem.description = %q{A Kiseru client for Trello}
|
8
|
+
gem.summary = %q{A Kiseru client for Trello}
|
9
|
+
gem.homepage = ""
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "ki_trello"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = KiTrello::VERSION
|
17
|
+
|
18
|
+
gem.add_dependency('colored', '~> 1.2.0')
|
19
|
+
gem.add_dependency('faraday', '~> 0.8.2')
|
20
|
+
gem.add_dependency('faraday_middleware', '~> 0.8.8')
|
21
|
+
gem.add_dependency('gli', '~> 1.6.0')
|
22
|
+
gem.add_dependency('multi_json', '~> 1.3.6')
|
23
|
+
gem.add_dependency('json_pure', '~> 1.7.4')
|
24
|
+
|
25
|
+
gem.add_development_dependency('debugger', '~> 1.2.0')
|
26
|
+
gem.add_development_dependency('rake', '~> 0.9.2')
|
27
|
+
gem.add_development_dependency('rspec', '~> 2.11.0')
|
28
|
+
gem.add_development_dependency('simplecov', '~> 0.6.4')
|
29
|
+
gem.add_development_dependency('test-construct', '~> 1.2.0')
|
30
|
+
gem.add_development_dependency('vcr', '~> 2.2.4')
|
31
|
+
gem.add_development_dependency('webmock', '~> 1.8.9')
|
32
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module KiTrello
|
2
|
+
|
3
|
+
class Command
|
4
|
+
|
5
|
+
attr_reader :input, :output, :error, :config
|
6
|
+
|
7
|
+
def initialize(input=$stdin, output=$stdout, error=$stderr, config = Kiseru::Config[:ki_trello])
|
8
|
+
@input = input
|
9
|
+
@output = output
|
10
|
+
@error = error
|
11
|
+
@config = config
|
12
|
+
@pretty = true
|
13
|
+
end
|
14
|
+
|
15
|
+
def list_boards
|
16
|
+
output.puts(boards)
|
17
|
+
end
|
18
|
+
|
19
|
+
def get_card(card_id)
|
20
|
+
output.puts(card(card_id))
|
21
|
+
end
|
22
|
+
|
23
|
+
def create_card(opts = {})
|
24
|
+
list_id = opts.fetch(:list)
|
25
|
+
json = input.read
|
26
|
+
session = Session.new(@config)
|
27
|
+
data = MultiJson.load(json)
|
28
|
+
card = session.new_card(list_id, data)
|
29
|
+
output.puts(MultiJson.dump(card, :pretty => @pretty))
|
30
|
+
end
|
31
|
+
|
32
|
+
def list_lists(board_id)
|
33
|
+
output.puts(lists(board_id))
|
34
|
+
end
|
35
|
+
|
36
|
+
def card(card_id)
|
37
|
+
session = Session.new(@config)
|
38
|
+
card_data = session.card(extract_id(card_id))
|
39
|
+
MultiJson.dump(card_data, :pretty => @pretty)
|
40
|
+
end
|
41
|
+
|
42
|
+
def lists(board_id)
|
43
|
+
session = Session.new(@config)
|
44
|
+
list_data = session.lists(board_id)
|
45
|
+
MultiJson.dump(list_data, :pretty => @pretty)
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
def boards
|
50
|
+
session = Session.new(@config)
|
51
|
+
board_data = session.boards
|
52
|
+
MultiJson.dump(board_data, :pretty => @pretty)
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def extract_id(id)
|
58
|
+
if id=~%r{https://trello.com/c/(.*)}
|
59
|
+
$1
|
60
|
+
else
|
61
|
+
id
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
# TODO - this is duplicated in ki_pivotal
|
2
|
+
|
3
|
+
module KiTrello
|
4
|
+
|
5
|
+
class Interactive
|
6
|
+
# "Resistance is futile!", "We will get an answer!"
|
7
|
+
def self.repeatedly_ask(question)
|
8
|
+
response = ""
|
9
|
+
while response == ""
|
10
|
+
response = simple_query(question)
|
11
|
+
end
|
12
|
+
response
|
13
|
+
end
|
14
|
+
# "We have ways of making you talk!"
|
15
|
+
def self.repeatedly_choose_from(things, question)
|
16
|
+
index = nil
|
17
|
+
while index.nil?
|
18
|
+
index = choose_from_many(things, question)
|
19
|
+
end
|
20
|
+
index
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.choose_from_many(things, question)
|
24
|
+
$stderr.puts "\n "+question
|
25
|
+
|
26
|
+
things.each_with_index { |thing, index| $stderr.puts " #{index+1} ".green + " #{thing}" }
|
27
|
+
|
28
|
+
index = ( (simple_query( "Enter an index (#{(1..things.size)})" ).to_i) - 1 )
|
29
|
+
index = ( index >= 0 && index < things.size ) ? index : nil
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.simple_query(prompt)
|
33
|
+
if prompt.nil?
|
34
|
+
$stderr.print "\n> "
|
35
|
+
else
|
36
|
+
$stderr.print "\n #{prompt}: "
|
37
|
+
end
|
38
|
+
$stdin.gets.chomp
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.select_board(prompt)
|
42
|
+
boards = MultiJson.load(KiTrello::Command.new.boards)
|
43
|
+
if boards.size > 1
|
44
|
+
index = repeatedly_choose_from(boards.map { |b| b['name'] }, prompt)
|
45
|
+
else
|
46
|
+
index = 0
|
47
|
+
end
|
48
|
+
$stderr.puts "\n Chosen board is #{boards[index]['name']}"
|
49
|
+
boards[index]['id']
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.select_story(project_id, prompt)
|
53
|
+
stories = MultiJson.load(KiPivotal::Api.new.stories_in_project(project_id))
|
54
|
+
|
55
|
+
if stories.size > 1
|
56
|
+
index = repeatedly_choose_from(stories.map { |p| p['name'] }, prompt)
|
57
|
+
else
|
58
|
+
index = 0
|
59
|
+
end
|
60
|
+
|
61
|
+
$stderr.puts "\n Chosen story is '#{stories[index]['name']}'"
|
62
|
+
stories[index]['id']
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.select_project(prompt)
|
66
|
+
projects = MultiJson.load(KiPivotal::Api.new.projects)
|
67
|
+
|
68
|
+
if projects.size > 1
|
69
|
+
index = repeatedly_choose_from(projects.map { |p| p['name'] }, prompt)
|
70
|
+
else
|
71
|
+
index = 0
|
72
|
+
end
|
73
|
+
|
74
|
+
$stderr.puts "\n Chosen project is '#{projects[index]['name']}'"
|
75
|
+
projects[index]['id']
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.new_story
|
79
|
+
name = repeatedly_ask("Name of story")
|
80
|
+
|
81
|
+
description = repeatedly_ask("Description of story")
|
82
|
+
|
83
|
+
types = ["bug","feature","release","chore"]
|
84
|
+
type = types[repeatedly_choose_from(types, "What type of story is this?")]
|
85
|
+
|
86
|
+
{
|
87
|
+
name: name,
|
88
|
+
description: description,
|
89
|
+
story_type: type,
|
90
|
+
requested_by: 'Kiseru',
|
91
|
+
ki_type: 'pivotal_story'
|
92
|
+
}.to_json
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# TODO - this is duplicated in ki_pivotal and ki_youtrack
|
2
|
+
|
3
|
+
require 'pathname'
|
4
|
+
require 'fileutils'
|
5
|
+
require 'yaml/store'
|
6
|
+
|
7
|
+
module Kiseru
|
8
|
+
|
9
|
+
class ConfigError < StandardError; end;
|
10
|
+
|
11
|
+
class ConfigDir
|
12
|
+
|
13
|
+
NAME = '.kiseru'
|
14
|
+
|
15
|
+
attr_reader :path
|
16
|
+
|
17
|
+
def initialize(opts = {})
|
18
|
+
name = opts.fetch(:name) { NAME }
|
19
|
+
root = Pathname.new(File.expand_path(opts.fetch(:root) { '~' }))
|
20
|
+
@path = root + name
|
21
|
+
unless File.directory?(@path)
|
22
|
+
Dir.mkdir(@path)
|
23
|
+
FileUtils.chmod(0700, @path)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def config(app_name)
|
28
|
+
Config.new(@path, app_name)
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
class Config
|
34
|
+
|
35
|
+
attr_reader :path
|
36
|
+
|
37
|
+
def self.[](key)
|
38
|
+
ConfigDir.new.config(key)
|
39
|
+
end
|
40
|
+
|
41
|
+
def initialize(root_path, app_name)
|
42
|
+
@path = (root_path + "#{app_name}.yml").to_s
|
43
|
+
unless File.exists?(@path)
|
44
|
+
FileUtils.touch(@path)
|
45
|
+
FileUtils.chmod(0600, @path)
|
46
|
+
end
|
47
|
+
@store = YAML::Store.new(@path)
|
48
|
+
@store.transaction do
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def ensure_present(*keys)
|
53
|
+
keys.each do |key|
|
54
|
+
if read(key).nil?
|
55
|
+
raise ConfigError, "'#{key}' is not defined in config"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def write(key, value)
|
61
|
+
@store.transaction do
|
62
|
+
@store[key] = value
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def read(key)
|
67
|
+
@store.transaction(read_only=true) do
|
68
|
+
@store[key]
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module KiTrello
|
2
|
+
|
3
|
+
class SessionError < StandardError; end;
|
4
|
+
|
5
|
+
class Session
|
6
|
+
|
7
|
+
API_URL = "https://api.trello.com"
|
8
|
+
|
9
|
+
def initialize(config)
|
10
|
+
@config = config
|
11
|
+
@config.ensure_present('username', 'developer_api_key', 'member_token')
|
12
|
+
@username = config.read('username')
|
13
|
+
@key = config.read('developer_api_key')
|
14
|
+
@token = config.read('member_token')
|
15
|
+
end
|
16
|
+
|
17
|
+
def auth_params
|
18
|
+
{
|
19
|
+
:key => @key,
|
20
|
+
:token => @token
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
def lists(board_id)
|
25
|
+
response = connection.get("/1/boards/#{board_id}/lists", auth_params)
|
26
|
+
case response.status
|
27
|
+
when 200
|
28
|
+
response.body
|
29
|
+
else
|
30
|
+
raise SessionError, "Unhandled status code #{response.status}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def card(card_id)
|
35
|
+
response = connection.get("/1/cards/#{card_id}", auth_params)
|
36
|
+
|
37
|
+
case response.status
|
38
|
+
when 200
|
39
|
+
response.body
|
40
|
+
else
|
41
|
+
debugger
|
42
|
+
raise SessionError, "Unhandled status code #{response.status}"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def new_card(list_id, data)
|
47
|
+
params = data.merge(auth_params).merge(:idList => list_id)
|
48
|
+
response = connection.post("/1/cards", params)
|
49
|
+
|
50
|
+
case response.status
|
51
|
+
when 200
|
52
|
+
response.body
|
53
|
+
when 400
|
54
|
+
raise SessionError, "Bad parameters. Check the JSON.\n#{response.body}"
|
55
|
+
else
|
56
|
+
raise SessionError, "Unhandled status code #{response.status}"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def boards
|
61
|
+
response = connection.get("/1/members/#{@username}/boards", auth_params)
|
62
|
+
case response.status
|
63
|
+
when 200
|
64
|
+
response.body
|
65
|
+
else
|
66
|
+
raise SessionError, "Unhandled status code #{response.status}"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def connection
|
73
|
+
@connection ||= Faraday.new(:url => API_URL) do |faraday|
|
74
|
+
faraday.request :url_encoded # form-encode POST params
|
75
|
+
if ENV['DEBUG']=='true'
|
76
|
+
faraday.response :logger # log requests to STDOUT
|
77
|
+
end
|
78
|
+
faraday.response :json, :content_type => /\bjavascript$/
|
79
|
+
faraday.response :json, :content_type => /\bjson$/
|
80
|
+
faraday.adapter Faraday.default_adapter # make requests with Net::HTTP
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
|
87
|
+
end
|
data/lib/ki_trello.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require "ki_trello/version"
|
2
|
+
require 'json'
|
3
|
+
require "multi_json"
|
4
|
+
require "faraday"
|
5
|
+
require "faraday_middleware"
|
6
|
+
|
7
|
+
autoload :Kiseru, 'ki_trello/kiseru'
|
8
|
+
|
9
|
+
module KiTrello
|
10
|
+
|
11
|
+
autoload :Command, "ki_trello/command"
|
12
|
+
autoload :Interactive, "ki_trello/interactive"
|
13
|
+
autoload :Session, "ki_trello/session"
|
14
|
+
|
15
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Command do
|
4
|
+
|
5
|
+
let(:config) do
|
6
|
+
Kiseru::ConfigDir.new(:root => SPEC_DIR,
|
7
|
+
:name => SPEC_CONFIG_DIR).config(:ki_trello)
|
8
|
+
end
|
9
|
+
|
10
|
+
def with_command(input_string="")
|
11
|
+
input = StringIO.new(input_string)
|
12
|
+
error = StringIO.new
|
13
|
+
output = StringIO.new
|
14
|
+
command = Command.new(input, output, error, config)
|
15
|
+
yield command
|
16
|
+
output.rewind
|
17
|
+
error.rewind
|
18
|
+
[output.read, error.read]
|
19
|
+
end
|
20
|
+
|
21
|
+
def as_data(json)
|
22
|
+
MultiJson.load(json)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "gets boards", :vcr do
|
26
|
+
out, err = with_command do |command|
|
27
|
+
command.list_boards
|
28
|
+
end
|
29
|
+
boards = as_data(out)
|
30
|
+
boards.length.should > 0
|
31
|
+
boards.first['id'].should_not be_nil
|
32
|
+
boards.first['name'].should_not be_nil
|
33
|
+
end
|
34
|
+
|
35
|
+
it "gets lists in board", :vcr do
|
36
|
+
out, err = with_command do |command|
|
37
|
+
command.list_lists("502d05b437e302c37e6beff0")
|
38
|
+
end
|
39
|
+
lists = as_data(out)
|
40
|
+
lists.length.should > 0
|
41
|
+
lists.first['id'].should_not be_nil
|
42
|
+
lists.first['name'].should == "For testing"
|
43
|
+
end
|
44
|
+
|
45
|
+
it "gets card by ID, short ID, or short URL", :vcr do
|
46
|
+
out, err = with_command do |command|
|
47
|
+
command.get_card("502d6b81a1dd427b1115f43b")
|
48
|
+
end
|
49
|
+
|
50
|
+
card = as_data(out)
|
51
|
+
card['name'].should == "Test card 001"
|
52
|
+
|
53
|
+
# Sorry for this test, not sure how to get the short name
|
54
|
+
out, err = with_command do |command|
|
55
|
+
command.get_card("QVzGecRj")
|
56
|
+
end
|
57
|
+
|
58
|
+
card = as_data(out)
|
59
|
+
card['name'].should == "Test card 001"
|
60
|
+
|
61
|
+
out, err = with_command do |command|
|
62
|
+
command.get_card("https://trello.com/c/QVzGecRj")
|
63
|
+
end
|
64
|
+
|
65
|
+
card = as_data(out)
|
66
|
+
card['name'].should == "Test card 001"
|
67
|
+
end
|
68
|
+
|
69
|
+
it "creates card in board", :vcr do
|
70
|
+
json =<<-JSON
|
71
|
+
{
|
72
|
+
"name" : "fake card"
|
73
|
+
}
|
74
|
+
JSON
|
75
|
+
out, err = with_command(json) do |command|
|
76
|
+
command.create_card(:list => "502d1745f52455c97e995cf0")
|
77
|
+
end
|
78
|
+
created_card = as_data(out)
|
79
|
+
created_card['name'].should == "fake card"
|
80
|
+
created_card['idList'].should == "502d1745f52455c97e995cf0"
|
81
|
+
|
82
|
+
out, err = with_command do |command|
|
83
|
+
command.get_card(created_card['id'])
|
84
|
+
end
|
85
|
+
card = as_data(out)
|
86
|
+
card['name'].should == "fake card"
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
|
91
|
+
end
|
92
|
+
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'ki_trello'
|
2
|
+
require 'construct'
|
3
|
+
require 'pp'
|
4
|
+
require 'vcr'
|
5
|
+
|
6
|
+
include Construct::Helpers
|
7
|
+
include KiTrello
|
8
|
+
|
9
|
+
SPEC_DIR = File.expand_path(File.dirname(__FILE__))
|
10
|
+
SPEC_CONFIG_DIR = 'configs'
|
11
|
+
|
12
|
+
if [0, 'false', false, 'f', 'n', 'no', 'off'].include?(ENV['VCR'])
|
13
|
+
puts "VCR off"
|
14
|
+
else
|
15
|
+
puts "VCR on!"
|
16
|
+
VCR.configure do |c|
|
17
|
+
c.cassette_library_dir = 'spec/fixtures/vcr_cassettes'
|
18
|
+
c.hook_into :webmock
|
19
|
+
c.allow_http_connections_when_no_cassette = true
|
20
|
+
c.configure_rspec_metadata!
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
if ENV['COVERAGE']
|
25
|
+
require 'simplecov'
|
26
|
+
SimpleCov.start
|
27
|
+
end
|
28
|
+
|
29
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
30
|
+
RSpec.configure do |config|
|
31
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
32
|
+
config.run_all_when_everything_filtered = true
|
33
|
+
config.filter_run :focus
|
34
|
+
|
35
|
+
# Run specs in random order to surface order dependencies. If you find an
|
36
|
+
# order dependency and want to debug it, you can fix the order by providing
|
37
|
+
# the seed, which is printed after each run.
|
38
|
+
# --seed 1234
|
39
|
+
config.order = 'random'
|
40
|
+
end
|
metadata
ADDED
@@ -0,0 +1,207 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ki_trello
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Ben Brinckerhoff
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-08-20 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: colored
|
16
|
+
requirement: &70265363867020 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 1.2.0
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70265363867020
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: faraday
|
27
|
+
requirement: &70265363866520 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 0.8.2
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70265363866520
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: faraday_middleware
|
38
|
+
requirement: &70265363866060 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 0.8.8
|
44
|
+
type: :runtime
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70265363866060
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: gli
|
49
|
+
requirement: &70265363865560 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.6.0
|
55
|
+
type: :runtime
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *70265363865560
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: multi_json
|
60
|
+
requirement: &70265363865040 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ~>
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: 1.3.6
|
66
|
+
type: :runtime
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *70265363865040
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: json_pure
|
71
|
+
requirement: &70265363864560 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ~>
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: 1.7.4
|
77
|
+
type: :runtime
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: *70265363864560
|
80
|
+
- !ruby/object:Gem::Dependency
|
81
|
+
name: debugger
|
82
|
+
requirement: &70265363864100 !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ~>
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: 1.2.0
|
88
|
+
type: :development
|
89
|
+
prerelease: false
|
90
|
+
version_requirements: *70265363864100
|
91
|
+
- !ruby/object:Gem::Dependency
|
92
|
+
name: rake
|
93
|
+
requirement: &70265363863640 !ruby/object:Gem::Requirement
|
94
|
+
none: false
|
95
|
+
requirements:
|
96
|
+
- - ~>
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: 0.9.2
|
99
|
+
type: :development
|
100
|
+
prerelease: false
|
101
|
+
version_requirements: *70265363863640
|
102
|
+
- !ruby/object:Gem::Dependency
|
103
|
+
name: rspec
|
104
|
+
requirement: &70265363863180 !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ~>
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: 2.11.0
|
110
|
+
type: :development
|
111
|
+
prerelease: false
|
112
|
+
version_requirements: *70265363863180
|
113
|
+
- !ruby/object:Gem::Dependency
|
114
|
+
name: simplecov
|
115
|
+
requirement: &70265363862720 !ruby/object:Gem::Requirement
|
116
|
+
none: false
|
117
|
+
requirements:
|
118
|
+
- - ~>
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
version: 0.6.4
|
121
|
+
type: :development
|
122
|
+
prerelease: false
|
123
|
+
version_requirements: *70265363862720
|
124
|
+
- !ruby/object:Gem::Dependency
|
125
|
+
name: test-construct
|
126
|
+
requirement: &70265363862260 !ruby/object:Gem::Requirement
|
127
|
+
none: false
|
128
|
+
requirements:
|
129
|
+
- - ~>
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: 1.2.0
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: *70265363862260
|
135
|
+
- !ruby/object:Gem::Dependency
|
136
|
+
name: vcr
|
137
|
+
requirement: &70265363861800 !ruby/object:Gem::Requirement
|
138
|
+
none: false
|
139
|
+
requirements:
|
140
|
+
- - ~>
|
141
|
+
- !ruby/object:Gem::Version
|
142
|
+
version: 2.2.4
|
143
|
+
type: :development
|
144
|
+
prerelease: false
|
145
|
+
version_requirements: *70265363861800
|
146
|
+
- !ruby/object:Gem::Dependency
|
147
|
+
name: webmock
|
148
|
+
requirement: &70265363861340 !ruby/object:Gem::Requirement
|
149
|
+
none: false
|
150
|
+
requirements:
|
151
|
+
- - ~>
|
152
|
+
- !ruby/object:Gem::Version
|
153
|
+
version: 1.8.9
|
154
|
+
type: :development
|
155
|
+
prerelease: false
|
156
|
+
version_requirements: *70265363861340
|
157
|
+
description: A Kiseru client for Trello
|
158
|
+
email:
|
159
|
+
- ben@freeagent.com
|
160
|
+
executables:
|
161
|
+
- ki_trello
|
162
|
+
extensions: []
|
163
|
+
extra_rdoc_files: []
|
164
|
+
files:
|
165
|
+
- .gitignore
|
166
|
+
- .rspec
|
167
|
+
- Gemfile
|
168
|
+
- LICENSE
|
169
|
+
- README.md
|
170
|
+
- Rakefile
|
171
|
+
- bin/ki_trello
|
172
|
+
- ki_trello.gemspec
|
173
|
+
- lib/ki_trello.rb
|
174
|
+
- lib/ki_trello/command.rb
|
175
|
+
- lib/ki_trello/interactive.rb
|
176
|
+
- lib/ki_trello/kiseru.rb
|
177
|
+
- lib/ki_trello/session.rb
|
178
|
+
- lib/ki_trello/version.rb
|
179
|
+
- spec/integration/command_spec.rb
|
180
|
+
- spec/spec_helper.rb
|
181
|
+
homepage: ''
|
182
|
+
licenses: []
|
183
|
+
post_install_message:
|
184
|
+
rdoc_options: []
|
185
|
+
require_paths:
|
186
|
+
- lib
|
187
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
188
|
+
none: false
|
189
|
+
requirements:
|
190
|
+
- - ! '>='
|
191
|
+
- !ruby/object:Gem::Version
|
192
|
+
version: '0'
|
193
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
194
|
+
none: false
|
195
|
+
requirements:
|
196
|
+
- - ! '>='
|
197
|
+
- !ruby/object:Gem::Version
|
198
|
+
version: '0'
|
199
|
+
requirements: []
|
200
|
+
rubyforge_project:
|
201
|
+
rubygems_version: 1.8.10
|
202
|
+
signing_key:
|
203
|
+
specification_version: 3
|
204
|
+
summary: A Kiseru client for Trello
|
205
|
+
test_files:
|
206
|
+
- spec/integration/command_spec.rb
|
207
|
+
- spec/spec_helper.rb
|