donedone 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
 - data/.gitignore +18 -0
 - data/Gemfile +4 -0
 - data/MIT-LICENSE +7 -0
 - data/README.md +73 -0
 - data/Rakefile +13 -0
 - data/bin/donedone +25 -0
 - data/donedone.gemspec +25 -0
 - data/examples/lighthouse_csv_importer.rb +72 -0
 - data/lib/donedone.rb +5 -0
 - data/lib/donedone/constant.rb +33 -0
 - data/lib/donedone/http.rb +131 -0
 - data/lib/donedone/issue_tracker.rb +248 -0
 - data/lib/donedone/multipart.rb +78 -0
 - data/lib/donedone/version.rb +3 -0
 - data/spec/donedone/constant_spec.rb +17 -0
 - data/spec/donedone/http_spec.rb +101 -0
 - data/spec/donedone/issue_tracker_spec.rb +164 -0
 - data/spec/spec_helper.rb +12 -0
 - metadata +95 -0
 
    
        checksums.yaml
    ADDED
    
    | 
         @@ -0,0 +1,7 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            ---
         
     | 
| 
      
 2 
     | 
    
         
            +
            SHA1:
         
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 85ea18b103a503e2eda28b1f26ef959019a20442
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 4f1593a019af558f1f167d21691d6d01b367a106
         
     | 
| 
      
 5 
     | 
    
         
            +
            SHA512:
         
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: c458cef331617286b28a74dab64132178ea91e05ed25aa930787afd6c3da7d544ed2f82e49e5779a2d83220580f3a4f985a580742978aafeb5f30444dff5ec55
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: c0ae992671cecbf2750f4dd71c9e05d9bf928752ea26448f749f93d2bcbe3797cd7545822d11dba20d56eed0d016bbf46e62cd0f918055c53415901fd0d87441
         
     | 
    
        data/.gitignore
    ADDED
    
    
    
        data/Gemfile
    ADDED
    
    
    
        data/MIT-LICENSE
    ADDED
    
    | 
         @@ -0,0 +1,7 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            Copyright (c) 2013 Inquisitive Minds, Inc
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
         
     | 
    
        data/README.md
    ADDED
    
    | 
         @@ -0,0 +1,73 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # DoneDone API Ruby Client Library (GEM)
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            ## REQUIREMENT
         
     | 
| 
      
 4 
     | 
    
         
            +
            Ruby
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            ## USAGE
         
     | 
| 
      
 7 
     | 
    
         
            +
            To use the Ruby library with a DoneDone project, you will need to enable the API option under the Project Settings page.
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            Please see http://www.getdonedone.com/api for more detailed documentation.
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            The examples below work for projects with the API enabled.
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
            ## EXAMPLES
         
     | 
| 
      
 15 
     | 
    
         
            +
            ```
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
            # use it in your own code:
         
     | 
| 
      
 18 
     | 
    
         
            +
            cmd-prompt> gem install 'donedone'
         
     | 
| 
      
 19 
     | 
    
         
            +
            require 'donedone'
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
            # or interact via donedone ruby-cmd
         
     | 
| 
      
 22 
     | 
    
         
            +
            cmd-prompt> donedone -h
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
            # import your LightHouse CSV:
         
     | 
| 
      
 25 
     | 
    
         
            +
            ./examples/lighthouse_csv_importer.rb <domain> <usr> <pwd> <project_id> /path/to/your/light_house.csv
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
            # or via irb
         
     | 
| 
      
 28 
     | 
    
         
            +
            cmd-prompt> irb
         
     | 
| 
      
 29 
     | 
    
         
            +
            require 'donedone'
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
            domain = "YOUR_COMPANY_DOMAIN" #e.g. wearemammoth
         
     | 
| 
      
 32 
     | 
    
         
            +
            username = "YOUR_USERNAME"
         
     | 
| 
      
 33 
     | 
    
         
            +
            password = "YOUR_PASSWORD"
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
            issue_tracker = DoneDone::IssueTracker.new(domain, username, password)
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
            # list all the api calls (plus the 'result' method):
         
     | 
| 
      
 38 
     | 
    
         
            +
            issue_tracker.public_methods(false)
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
            issue_tracker.projects
         
     | 
| 
      
 41 
     | 
    
         
            +
            project_id = issue_tracker.result.first["ID"]
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
            issue_tracker.priority_levels
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
            issue_tracker.people_in_project(project_id)
         
     | 
| 
      
 46 
     | 
    
         
            +
              tester_id = issue_tracker.result.first["ID"]
         
     | 
| 
      
 47 
     | 
    
         
            +
              resolver_id = issue_tracker.result.last["ID"]
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
            issue_tracker.issues_in_project(project_id)
         
     | 
| 
      
 50 
     | 
    
         
            +
              priority_level_id = issue_tracker.result.first["PriorityLevelID"]
         
     | 
| 
      
 51 
     | 
    
         
            +
              issue_id = issue_tracker.result.first["OrderNumber"]
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
            issue_tracker.issue_exist?(project_id, issue_id)
         
     | 
| 
      
 54 
     | 
    
         
            +
            issue_tracker.potential_statuses_for_issue(project_id, issue_id)
         
     | 
| 
      
 55 
     | 
    
         
            +
            issue_tracker.issue(project_id, issue_id)
         
     | 
| 
      
 56 
     | 
    
         
            +
            issue_tracker.people_for_issue_assignment(project_id, issue_id)
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
            new_issue_id = issue_tracker.create_issue(project_id, title, priority_id,
         
     | 
| 
      
 59 
     | 
    
         
            +
            resolver_id, tester_id, {:description => '', :tags=> nil, :watcher_id=>nil, :attachments=>nil})
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
            comment = "blah blah"
         
     | 
| 
      
 62 
     | 
    
         
            +
            file_name = "./file1.txt"
         
     | 
| 
      
 63 
     | 
    
         
            +
            File.open(file_name, "w") {|f| f.puts "attachment one." }
         
     | 
| 
      
 64 
     | 
    
         
            +
            comment_url = issue_tracker.create_comment(project_id, new_issue_id, comment, {:people_to_cc_ids=>nil :attachments=>[file_name]})
         
     | 
| 
      
 65 
     | 
    
         
            +
            puts issue_tracker.result["SuccesfullyAttachedFiles"] ? "attachment uploaded successfully" : "failed to upload attachment"
         
     | 
| 
      
 66 
     | 
    
         
            +
            File.unlink(file_name)
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
            issue_url = issue_tracker.update_issue(project_id, new_issue_id, {:title=>nil, :priority_id=>nil, :resolver_id=>nil, :tester_id=nil, :description=>nil, :tags=>nil, :state_id=>nil, :attachments=>nil})
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
            ```
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
            ## TODO
         
     | 
| 
      
 73 
     | 
    
         
            +
            improve design via specs
         
     | 
    
        data/Rakefile
    ADDED
    
    | 
         @@ -0,0 +1,13 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "bundler/gem_tasks"
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require "rspec/core/rake_task"
         
     | 
| 
      
 4 
     | 
    
         
            +
            RSpec::Core::RakeTask.new(:spec)
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            gemspec = eval(File.read("donedone.gemspec"))
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            task :build => "#{gemspec.full_name}.gem"
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            file "#{gemspec.full_name}.gem" => gemspec.files + ["donedone.gemspec"] do
         
     | 
| 
      
 11 
     | 
    
         
            +
              system "gem build donedone.gemspec"
         
     | 
| 
      
 12 
     | 
    
         
            +
              system "gem install donedone-#{DoneDone::VERSION}.gem"
         
     | 
| 
      
 13 
     | 
    
         
            +
            end
         
     | 
    
        data/bin/donedone
    ADDED
    
    | 
         @@ -0,0 +1,25 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/env ruby
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            begin
         
     | 
| 
      
 4 
     | 
    
         
            +
              require 'rubygems'
         
     | 
| 
      
 5 
     | 
    
         
            +
              gem 'donedone'
         
     | 
| 
      
 6 
     | 
    
         
            +
            rescue LoadError
         
     | 
| 
      
 7 
     | 
    
         
            +
            end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            begin
         
     | 
| 
      
 10 
     | 
    
         
            +
              require 'donedone'
         
     | 
| 
      
 11 
     | 
    
         
            +
            rescue LoadError
         
     | 
| 
      
 12 
     | 
    
         
            +
              require_relative '../lib/donedone'
         
     | 
| 
      
 13 
     | 
    
         
            +
            end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            if ([] == ARGV) || ARGV.length < 4 || (ARGV[0].start_with?("-h"))
         
     | 
| 
      
 16 
     | 
    
         
            +
              warn "USAGE: ${$0} <domain> <usr> <pwd> <api-method> [args...]"
         
     | 
| 
      
 17 
     | 
    
         
            +
              exit
         
     | 
| 
      
 18 
     | 
    
         
            +
            end
         
     | 
| 
      
 19 
     | 
    
         
            +
            init_args = []
         
     | 
| 
      
 20 
     | 
    
         
            +
            # puts "ARGV start: #{ARGV.inspect}"
         
     | 
| 
      
 21 
     | 
    
         
            +
            3.times { init_args << ARGV.shift }
         
     | 
| 
      
 22 
     | 
    
         
            +
            # puts "ARGV now: #{ARGV.inspect}"
         
     | 
| 
      
 23 
     | 
    
         
            +
            issue_tracker = DoneDone::IssueTracker.new(*init_args)
         
     | 
| 
      
 24 
     | 
    
         
            +
            puts issue_tracker.send(ARGV.shift, *ARGV)
         
     | 
| 
      
 25 
     | 
    
         
            +
            exit
         
     | 
    
        data/donedone.gemspec
    ADDED
    
    | 
         @@ -0,0 +1,25 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # -*- encoding: utf-8 -*-
         
     | 
| 
      
 2 
     | 
    
         
            +
            $:.push File.expand_path("../lib", __FILE__)
         
     | 
| 
      
 3 
     | 
    
         
            +
            require "donedone/version"
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            Gem::Specification.new do |s|
         
     | 
| 
      
 6 
     | 
    
         
            +
              s.name        = "donedone"
         
     | 
| 
      
 7 
     | 
    
         
            +
              s.version     = DoneDone::VERSION
         
     | 
| 
      
 8 
     | 
    
         
            +
              s.authors     = ["Jonathan Thomas"]
         
     | 
| 
      
 9 
     | 
    
         
            +
              s.email       = ["buyer+donedone@his-service.net"]
         
     | 
| 
      
 10 
     | 
    
         
            +
              s.homepage    = "https://github.com/zoodles/DoneDone-API-Ruby"
         
     | 
| 
      
 11 
     | 
    
         
            +
              s.summary     = %q{donedone.com api client}
         
     | 
| 
      
 12 
     | 
    
         
            +
              s.description = %q{Check your existing todo items, add new ones, update old one}
         
     | 
| 
      
 13 
     | 
    
         
            +
              s.rubyforge_project = "donedone"
         
     | 
| 
      
 14 
     | 
    
         
            +
              s.license     = 'MIT'
         
     | 
| 
      
 15 
     | 
    
         
            +
              s.files         = `git ls-files`.split("\n")
         
     | 
| 
      
 16 
     | 
    
         
            +
              s.test_files    = `git ls-files -- {test,spec,features}/*`.split("\n")
         
     | 
| 
      
 17 
     | 
    
         
            +
              s.bindir        = 'bin'
         
     | 
| 
      
 18 
     | 
    
         
            +
              s.executables   = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
         
     | 
| 
      
 19 
     | 
    
         
            +
              s.require_paths = ["lib"]
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
              # specify any dependencies here; for example:
         
     | 
| 
      
 22 
     | 
    
         
            +
              s.add_dependency "mime-types", "~> 2.0"
         
     | 
| 
      
 23 
     | 
    
         
            +
              s.add_development_dependency "rspec", "~> 2.14.0"
         
     | 
| 
      
 24 
     | 
    
         
            +
              #s.add_development_dependency "simplecov"
         
     | 
| 
      
 25 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,72 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/env ruby
         
     | 
| 
      
 2 
     | 
    
         
            +
            # Import projct issues from LightHouse CSV exports
         
     | 
| 
      
 3 
     | 
    
         
            +
            # 
         
     | 
| 
      
 4 
     | 
    
         
            +
            # This is a simple example that migrates data from LightHouse to DoneDone using
         
     | 
| 
      
 5 
     | 
    
         
            +
            # the Ruby client. It makes a couple of assumptions. First, the CSV file must
         
     | 
| 
      
 6 
     | 
    
         
            +
            # contain columns listed below.
         
     | 
| 
      
 7 
     | 
    
         
            +
            # 
         
     | 
| 
      
 8 
     | 
    
         
            +
            # number | state | title | milestone | assigned | created | updated | project | tags
         
     | 
| 
      
 9 
     | 
    
         
            +
            # 
         
     | 
| 
      
 10 
     | 
    
         
            +
            # Second, it also assumes the accounts have already been created for the
         
     | 
| 
      
 11 
     | 
    
         
            +
            # project, and throws an execption if not. Because LightHouse handles things a
         
     | 
| 
      
 12 
     | 
    
         
            +
            # bit different from DoneDone, this script will also create the project with assignee
         
     | 
| 
      
 13 
     | 
    
         
            +
            # as both resolver and tester.
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            begin
         
     | 
| 
      
 16 
     | 
    
         
            +
              require 'rubygems'
         
     | 
| 
      
 17 
     | 
    
         
            +
              gem 'donedone'
         
     | 
| 
      
 18 
     | 
    
         
            +
            rescue LoadError
         
     | 
| 
      
 19 
     | 
    
         
            +
            end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
            begin
         
     | 
| 
      
 22 
     | 
    
         
            +
              require 'donedone'
         
     | 
| 
      
 23 
     | 
    
         
            +
            rescue LoadError
         
     | 
| 
      
 24 
     | 
    
         
            +
              require_relative '../lib/donedone'
         
     | 
| 
      
 25 
     | 
    
         
            +
            end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
            require 'csv'
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
            DEFAULT_DOMAIN = "Your company domain"
         
     | 
| 
      
 30 
     | 
    
         
            +
            domain = ARGV.shift || DEFAULT_DOMAIN
         
     | 
| 
      
 31 
     | 
    
         
            +
            username = ARGV.shift || "Your donedone username"
         
     | 
| 
      
 32 
     | 
    
         
            +
            password = ARGV.shift || "Your donedone password"
         
     | 
| 
      
 33 
     | 
    
         
            +
            project_id = ARGV.shift.to_i || "Your donedone project ID"
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
            CSVFilePath = ARGV.shift || "Path to the CSV file exported from lighthouseapp.com"
         
     | 
| 
      
 36 
     | 
    
         
            +
            priority_id = ARGV.shift || 2 #Assuming medium priority
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
            # puts "domain: #{domain.inspect}, username: #{username.inspect}, password: #{password.inspect}, project_id: #{project_id.inspect}, csv: #{CSVFilePath.inspect}"
         
     | 
| 
      
 39 
     | 
    
         
            +
            fail( "unknown file: #{CSVFilePath.inspect}") unless File.exists?(CSVFilePath)
         
     | 
| 
      
 40 
     | 
    
         
            +
            fail( "You must edit pass-in variables or edit the default values in #{$0}" ) if DEFAULT_DOMAIN == domain
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
            issue_tracker = DoneDone::IssueTracker.new(domain, username, password)
         
     | 
| 
      
 43 
     | 
    
         
            +
            project_peoples = issue_tracker.people_in_project(project_id)
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
            # read file
         
     | 
| 
      
 47 
     | 
    
         
            +
            csv_text = File.binread(CSVFilePath)
         
     | 
| 
      
 48 
     | 
    
         
            +
            # slurp
         
     | 
| 
      
 49 
     | 
    
         
            +
            csv = CSV.parse(csv_text, { :headers => true, :return_headers => false, :col_sep => ',', :quote_char =>  '"'})
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
            # loop over issues
         
     | 
| 
      
 52 
     | 
    
         
            +
            csv.each do |issue|
         
     | 
| 
      
 53 
     | 
    
         
            +
              # puts "i: #{issue.inspect}"
         
     | 
| 
      
 54 
     | 
    
         
            +
              person_id = nil
         
     | 
| 
      
 55 
     | 
    
         
            +
              name = issue['assigned']
         
     | 
| 
      
 56 
     | 
    
         
            +
              next if "" == project_peoples
         
     | 
| 
      
 57 
     | 
    
         
            +
              # puts "pp: #{project_peoples.inspect}"
         
     | 
| 
      
 58 
     | 
    
         
            +
              if person = project_peoples.detect{|people| people["Value"] == name}
         
     | 
| 
      
 59 
     | 
    
         
            +
                person_id = person["ID"]
         
     | 
| 
      
 60 
     | 
    
         
            +
              else
         
     | 
| 
      
 61 
     | 
    
         
            +
                fail "Fail to find DoneDone account for #{name}"
         
     | 
| 
      
 62 
     | 
    
         
            +
              end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
              # Create issue with medium priority
         
     | 
| 
      
 65 
     | 
    
         
            +
              print issue_tracker.create_issue(
         
     | 
| 
      
 66 
     | 
    
         
            +
                project_id, issue['title'], priority_id,
         
     | 
| 
      
 67 
     | 
    
         
            +
                person_id, person_id,
         
     | 
| 
      
 68 
     | 
    
         
            +
                {:description => "Created by DoneDone API Ruby client.", :tags => issue['tags']})
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
              # Pause execution for API request wait time.
         
     | 
| 
      
 71 
     | 
    
         
            +
              sleep(5)
         
     | 
| 
      
 72 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/donedone.rb
    ADDED
    
    
| 
         @@ -0,0 +1,33 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module DoneDone
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Constant
         
     | 
| 
      
 3 
     | 
    
         
            +
                PROJECTS_WITH_ISSUES = 'Projects/true' unless const_defined?(:PROJECTS_WITH_ISSUES)
         
     | 
| 
      
 4 
     | 
    
         
            +
                PROJECTS = 'Projects' unless const_defined?(:PROJECTS)
         
     | 
| 
      
 5 
     | 
    
         
            +
                PRIORITY_LEVELS = 'PriorityLevels' unless const_defined?(:PRIORITY_LEVELS)
         
     | 
| 
      
 6 
     | 
    
         
            +
                PEOPLE_IN_PROJECT = "PeopleInProject/%s" unless const_defined?(:PEOPLE_IN_PROJECT)
         
     | 
| 
      
 7 
     | 
    
         
            +
                ISSUES_IN_PROJECT = "IssuesInProject/%s" unless const_defined?(:ISSUES_IN_PROJECT)
         
     | 
| 
      
 8 
     | 
    
         
            +
                DOES_ISSUE_EXIST = "DoesIssueExist/%s/%s" unless const_defined?(:DOES_ISSUE_EXIST)
         
     | 
| 
      
 9 
     | 
    
         
            +
                POTENTIAL_STATUSES_FOR_ISSUE = "PotentialStatusesForIssue/%s/%s" unless const_defined?(:POTENTIAL_STATUSES_FOR_ISSUE)
         
     | 
| 
      
 10 
     | 
    
         
            +
                CREATE_ISSUE = "Issue/%s" unless const_defined?(:CREATE_ISSUE)
         
     | 
| 
      
 11 
     | 
    
         
            +
                ISSUE = "#{CREATE_ISSUE}/%s" unless const_defined?(:ISSUE)
         
     | 
| 
      
 12 
     | 
    
         
            +
                PEOPLE_FOR_ISSUE_ASSIGNMENT = "PeopleForIssueAssignment/%s/%s" unless const_defined?(:PEOPLE_FOR_ISSUE_ASSIGNMENT)
         
     | 
| 
      
 13 
     | 
    
         
            +
                COMMENT = "Comment/%s/%s" unless const_defined?(:COMMENT)
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                HOST = "%s.mydonedone.com" unless const_defined?(:HOST)
         
     | 
| 
      
 16 
     | 
    
         
            +
                PROTOCOL = "https" unless const_defined?(:PROTOCOL)
         
     | 
| 
      
 17 
     | 
    
         
            +
                BASE_URL_PATH = "IssueTracker/API" unless const_defined?(:BASE_URL_PATH)
         
     | 
| 
      
 18 
     | 
    
         
            +
                BASE_URL = "#{PROTOCOL}://%s/#{BASE_URL_PATH}/" unless const_defined?(:BASE_URL)
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                SSL_VERIFY_MODE = OpenSSL::SSL::VERIFY_NONE unless const_defined?(:SSL_VERIFY_MODE)
         
     | 
| 
      
 21 
     | 
    
         
            +
                SSL_VERSION = :SSLv3 unless const_defined?(:SSL_VERSION)
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                def self.url_for(name, *args)
         
     | 
| 
      
 24 
     | 
    
         
            +
                  format_str = const_get(name)
         
     | 
| 
      
 25 
     | 
    
         
            +
                  if args.empty?
         
     | 
| 
      
 26 
     | 
    
         
            +
                    format_str
         
     | 
| 
      
 27 
     | 
    
         
            +
                  else
         
     | 
| 
      
 28 
     | 
    
         
            +
                    format_str % args
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
                end
         
     | 
| 
      
 31 
     | 
    
         
            +
              end
         
     | 
| 
      
 32 
     | 
    
         
            +
            end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
         @@ -0,0 +1,131 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'net/https'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'uri'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require_relative 'multipart'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module DoneDone
         
     | 
| 
      
 6 
     | 
    
         
            +
              class Http
         
     | 
| 
      
 7 
     | 
    
         
            +
                attr_reader :domain, :data, :files, :method_url
         
     | 
| 
      
 8 
     | 
    
         
            +
                attr_reader :_request, :_debug
         
     | 
| 
      
 9 
     | 
    
         
            +
                private :_request
         
     | 
| 
      
 10 
     | 
    
         
            +
                private :_debug
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                attr_reader :put_class, :get_class, :post_class, :multipart_post_class
         
     | 
| 
      
 13 
     | 
    
         
            +
                attr_reader :http_class, :ssl_verify_mode, :ssl_version
         
     | 
| 
      
 14 
     | 
    
         
            +
                def initialize(domain, username, password, options={})
         
     | 
| 
      
 15 
     | 
    
         
            +
                  @domain = domain
         
     | 
| 
      
 16 
     | 
    
         
            +
                  @_username = username
         
     | 
| 
      
 17 
     | 
    
         
            +
                  @_password = password
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                  @put_class = options[:put_class] || Net::HTTP::Put
         
     | 
| 
      
 20 
     | 
    
         
            +
                  @get_class = options[:get_class] || Net::HTTP::Get
         
     | 
| 
      
 21 
     | 
    
         
            +
                  @post_class = options[:post_class] || Net::HTTP::Post
         
     | 
| 
      
 22 
     | 
    
         
            +
                  @multipart_post_class = options[:multipart_post_class] || Multipart::Post
         
     | 
| 
      
 23 
     | 
    
         
            +
                  @http_class = options[:http_class] || Net::HTTP
         
     | 
| 
      
 24 
     | 
    
         
            +
                  @ssl_verify_mode = options[:ssl_verify_mode] || Constant::SSL_VERIFY_MODE
         
     | 
| 
      
 25 
     | 
    
         
            +
                  @ssl_version = options[:ssl_version] || Constant::SSL_VERSION
         
     | 
| 
      
 26 
     | 
    
         
            +
                end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                def reset(options = {})
         
     | 
| 
      
 29 
     | 
    
         
            +
                  @data = options[:data]
         
     | 
| 
      
 30 
     | 
    
         
            +
                  @files = options[:files]
         
     | 
| 
      
 31 
     | 
    
         
            +
                  @_request = nil
         
     | 
| 
      
 32 
     | 
    
         
            +
                  @uri = nil
         
     | 
| 
      
 33 
     | 
    
         
            +
                  @base_url = nil
         
     | 
| 
      
 34 
     | 
    
         
            +
                  @host = nil
         
     | 
| 
      
 35 
     | 
    
         
            +
                  @http = nil
         
     | 
| 
      
 36 
     | 
    
         
            +
                  @_debug = options.has_key?(:debug) ? options[:debug] : false
         
     | 
| 
      
 37 
     | 
    
         
            +
                end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                def host
         
     | 
| 
      
 40 
     | 
    
         
            +
                  unless @host
         
     | 
| 
      
 41 
     | 
    
         
            +
                    @host = Constant.url_for('HOST', domain)
         
     | 
| 
      
 42 
     | 
    
         
            +
                  end
         
     | 
| 
      
 43 
     | 
    
         
            +
                  @host
         
     | 
| 
      
 44 
     | 
    
         
            +
                end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                def get(method_url, options={})
         
     | 
| 
      
 47 
     | 
    
         
            +
                  @method_url = method_url
         
     | 
| 
      
 48 
     | 
    
         
            +
                  reset(options)
         
     | 
| 
      
 49 
     | 
    
         
            +
                  request(get_class)
         
     | 
| 
      
 50 
     | 
    
         
            +
                end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                def put(method_url, options={})
         
     | 
| 
      
 53 
     | 
    
         
            +
                  @method_url = method_url
         
     | 
| 
      
 54 
     | 
    
         
            +
                  reset(options)
         
     | 
| 
      
 55 
     | 
    
         
            +
                  request(put_class) do
         
     | 
| 
      
 56 
     | 
    
         
            +
                    append_any_form_data
         
     | 
| 
      
 57 
     | 
    
         
            +
                  end
         
     | 
| 
      
 58 
     | 
    
         
            +
                end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                def post(method_url, options={})
         
     | 
| 
      
 61 
     | 
    
         
            +
                  @method_url = method_url
         
     | 
| 
      
 62 
     | 
    
         
            +
                  reset(options)
         
     | 
| 
      
 63 
     | 
    
         
            +
                  request(post_class) do
         
     | 
| 
      
 64 
     | 
    
         
            +
                    files ? append_multipart_data : append_any_form_data
         
     | 
| 
      
 65 
     | 
    
         
            +
                  end
         
     | 
| 
      
 66 
     | 
    
         
            +
                end
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
                private
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
                def http
         
     | 
| 
      
 72 
     | 
    
         
            +
                  unless @http
         
     | 
| 
      
 73 
     | 
    
         
            +
                    @http = http_class.new(uri.host, uri.port)
         
     | 
| 
      
 74 
     | 
    
         
            +
                    @http.use_ssl = true
         
     | 
| 
      
 75 
     | 
    
         
            +
                    @http.verify_mode = ssl_verify_mode
         
     | 
| 
      
 76 
     | 
    
         
            +
                    @http.ssl_version = ssl_version
         
     | 
| 
      
 77 
     | 
    
         
            +
                  end
         
     | 
| 
      
 78 
     | 
    
         
            +
                  @http
         
     | 
| 
      
 79 
     | 
    
         
            +
                end
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                def base_url
         
     | 
| 
      
 82 
     | 
    
         
            +
                  unless @base_url
         
     | 
| 
      
 83 
     | 
    
         
            +
                    @base_url = Constant.url_for('BASE_URL', host)
         
     | 
| 
      
 84 
     | 
    
         
            +
                  end
         
     | 
| 
      
 85 
     | 
    
         
            +
                  @base_url
         
     | 
| 
      
 86 
     | 
    
         
            +
                end
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
                def uri
         
     | 
| 
      
 89 
     | 
    
         
            +
                  unless @uri
         
     | 
| 
      
 90 
     | 
    
         
            +
                    @uri = URI.parse("#{base_url}#{method_url}")
         
     | 
| 
      
 91 
     | 
    
         
            +
                  end
         
     | 
| 
      
 92 
     | 
    
         
            +
                  @uri
         
     | 
| 
      
 93 
     | 
    
         
            +
                end
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
      
 95 
     | 
    
         
            +
                def request(method_class)
         
     | 
| 
      
 96 
     | 
    
         
            +
                  debug { "#{method_class.name}, #{uri.request_uri.inspect} - host: #{uri.host}, - port: #{uri.port}" }
         
     | 
| 
      
 97 
     | 
    
         
            +
                  @_request = method_class.new(uri.request_uri)
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
                  yield if block_given?
         
     | 
| 
      
 100 
     | 
    
         
            +
             
     | 
| 
      
 101 
     | 
    
         
            +
                  debug { "uri: #{uri.inspect}, files: #{files.inspect}" }
         
     | 
| 
      
 102 
     | 
    
         
            +
                  _request.basic_auth(@_username, @_password)
         
     | 
| 
      
 103 
     | 
    
         
            +
             
     | 
| 
      
 104 
     | 
    
         
            +
                  debug { "request: #{_request.to_hash.inspect}" }
         
     | 
| 
      
 105 
     | 
    
         
            +
                  http.request(_request)
         
     | 
| 
      
 106 
     | 
    
         
            +
                end
         
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
      
 108 
     | 
    
         
            +
                def append_any_form_data #(data=data)
         
     | 
| 
      
 109 
     | 
    
         
            +
                  if data
         
     | 
| 
      
 110 
     | 
    
         
            +
                    debug { "form_data: #{data.inspect}" }
         
     | 
| 
      
 111 
     | 
    
         
            +
                    _request.set_form_data(data)
         
     | 
| 
      
 112 
     | 
    
         
            +
                  end
         
     | 
| 
      
 113 
     | 
    
         
            +
                end
         
     | 
| 
      
 114 
     | 
    
         
            +
             
     | 
| 
      
 115 
     | 
    
         
            +
                def append_multipart_data #(files=files, data=data)
         
     | 
| 
      
 116 
     | 
    
         
            +
                  body, content_type, useragent =
         
     | 
| 
      
 117 
     | 
    
         
            +
                    multipart_post_class.prepare_query( files.merge(data) )
         
     | 
| 
      
 118 
     | 
    
         
            +
             
     | 
| 
      
 119 
     | 
    
         
            +
                  debug { "params: #{params.inspect}; body: #{body.inspect}, content_type: #{content_type.inspect}, useragent: #{useragent.inspect}" }
         
     | 
| 
      
 120 
     | 
    
         
            +
                  @_request.content_type = content_type
         
     | 
| 
      
 121 
     | 
    
         
            +
                  @_request.content_length = body.size
         
     | 
| 
      
 122 
     | 
    
         
            +
                  @_request["User-Agent"] = useragent
         
     | 
| 
      
 123 
     | 
    
         
            +
             
     | 
| 
      
 124 
     | 
    
         
            +
                  @_request.body = body
         
     | 
| 
      
 125 
     | 
    
         
            +
                end
         
     | 
| 
      
 126 
     | 
    
         
            +
             
     | 
| 
      
 127 
     | 
    
         
            +
                def debug
         
     | 
| 
      
 128 
     | 
    
         
            +
                  puts(yield) if _debug && block_given?
         
     | 
| 
      
 129 
     | 
    
         
            +
                end
         
     | 
| 
      
 130 
     | 
    
         
            +
              end
         
     | 
| 
      
 131 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,248 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require_relative "http"
         
     | 
| 
      
 2 
     | 
    
         
            +
            require_relative "constant"
         
     | 
| 
      
 3 
     | 
    
         
            +
            require "json"
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module DoneDone
         
     | 
| 
      
 6 
     | 
    
         
            +
              class IssueTracker
         
     | 
| 
      
 7 
     | 
    
         
            +
                HELPER_METHODS = [:response, :result] unless const_defined?(:HELPER_METHODS)
         
     | 
| 
      
 8 
     | 
    
         
            +
                def self.api_methods
         
     | 
| 
      
 9 
     | 
    
         
            +
                  instance_methods(false) - HELPER_METHODS
         
     | 
| 
      
 10 
     | 
    
         
            +
                end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                #Provide access to the DoneDone IssueTracker API.
         
     | 
| 
      
 13 
     | 
    
         
            +
                #See http://www.getdonedone.com/api for complete documentation for the
         
     | 
| 
      
 14 
     | 
    
         
            +
                #API.
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                attr_reader :response
         
     | 
| 
      
 17 
     | 
    
         
            +
                attr_reader :_debug
         
     | 
| 
      
 18 
     | 
    
         
            +
                private :_debug
         
     | 
| 
      
 19 
     | 
    
         
            +
                attr_reader :_http_helper
         
     | 
| 
      
 20 
     | 
    
         
            +
                private :_http_helper
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                #_debug - print debug messages
         
     | 
| 
      
 23 
     | 
    
         
            +
                #domain - company's DoneDone domain
         
     | 
| 
      
 24 
     | 
    
         
            +
                #username - DoneDone username
         
     | 
| 
      
 25 
     | 
    
         
            +
                #password - DoneDone password
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                def initialize(domain, username, password=nil, options = {})
         
     | 
| 
      
 28 
     | 
    
         
            +
                  @_debug = options.has_key?(:debug) ? options[:debug] : false
         
     | 
| 
      
 29 
     | 
    
         
            +
                  @_http_helper = options[:http_helper] || DoneDone::Http.new(domain, username, password)
         
     | 
| 
      
 30 
     | 
    
         
            +
                  @response = nil
         
     | 
| 
      
 31 
     | 
    
         
            +
                end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                def result
         
     | 
| 
      
 34 
     | 
    
         
            +
                  response ?  JSON.parse( response.body ) : ""
         
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                # Get all Projects with the API enabled
         
     | 
| 
      
 39 
     | 
    
         
            +
                # load_with_issues - Passing true will deep load all of the projects as
         
     | 
| 
      
 40 
     | 
    
         
            +
                # well as all of their active issues.
         
     | 
| 
      
 41 
     | 
    
         
            +
                def projects(load_with_issues=false)
         
     | 
| 
      
 42 
     | 
    
         
            +
                  url = load_with_issues ? Constant.url_for('PROJECTS_WITH_ISSUES') : Constant.url_for('PROJECTS')
         
     | 
| 
      
 43 
     | 
    
         
            +
                  api url
         
     | 
| 
      
 44 
     | 
    
         
            +
                end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                # Get priority levels
         
     | 
| 
      
 47 
     | 
    
         
            +
                def priority_levels
         
     | 
| 
      
 48 
     | 
    
         
            +
                  api Constant.url_for('PRIORITY_LEVELS')
         
     | 
| 
      
 49 
     | 
    
         
            +
                end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                # Get all people in a project
         
     | 
| 
      
 52 
     | 
    
         
            +
                # project_id - project id
         
     | 
| 
      
 53 
     | 
    
         
            +
                def people_in_project project_id
         
     | 
| 
      
 54 
     | 
    
         
            +
                  api Constant.url_for('PEOPLE_IN_PROJECT', project_id)
         
     | 
| 
      
 55 
     | 
    
         
            +
                end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                # Get all issues in a project
         
     | 
| 
      
 58 
     | 
    
         
            +
                # project_id - project id
         
     | 
| 
      
 59 
     | 
    
         
            +
                def issues_in_project project_id
         
     | 
| 
      
 60 
     | 
    
         
            +
                  api Constant.url_for('ISSUES_IN_PROJECT', project_id)
         
     | 
| 
      
 61 
     | 
    
         
            +
                end
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                # Check if an issue exists
         
     | 
| 
      
 64 
     | 
    
         
            +
                # project_id - project id
         
     | 
| 
      
 65 
     | 
    
         
            +
                # issue_id - issue id
         
     | 
| 
      
 66 
     | 
    
         
            +
                def issue_exist?(project_id, issue_id)
         
     | 
| 
      
 67 
     | 
    
         
            +
                  api Constant.url_for('DOES_ISSUE_EXIST', project_id, issue_id)
         
     | 
| 
      
 68 
     | 
    
         
            +
                  !result.empty? ? result["IssueExists"] : false
         
     | 
| 
      
 69 
     | 
    
         
            +
                end
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
                # Get potential statuses for issue
         
     | 
| 
      
 72 
     | 
    
         
            +
                # Note: If you are an admin, you'll get both all allowed statuses
         
     | 
| 
      
 73 
     | 
    
         
            +
                # as well as ALL statuses back from the server
         
     | 
| 
      
 74 
     | 
    
         
            +
                # project_id - project id
         
     | 
| 
      
 75 
     | 
    
         
            +
                # issue_id - issue id
         
     | 
| 
      
 76 
     | 
    
         
            +
                def potential_statuses_for_issue( project_id, issue_id)
         
     | 
| 
      
 77 
     | 
    
         
            +
                  api Constant.url_for('POTENTIAL_STATUSES_FOR_ISSUE', project_id, issue_id)
         
     | 
| 
      
 78 
     | 
    
         
            +
                end
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
                # Note: You can use this to check if an issue exists as well,
         
     | 
| 
      
 81 
     | 
    
         
            +
                # since it will return a 404 if the issue does not exist.
         
     | 
| 
      
 82 
     | 
    
         
            +
                def issue(project_id, issue_id)
         
     | 
| 
      
 83 
     | 
    
         
            +
                  api Constant.url_for('ISSUE', project_id, issue_id)
         
     | 
| 
      
 84 
     | 
    
         
            +
                end
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
                # Get a list of people that cane be assigend to an issue
         
     | 
| 
      
 87 
     | 
    
         
            +
                def people_for_issue_assignment(project_id, issue_id)
         
     | 
| 
      
 88 
     | 
    
         
            +
                  api Constant.url_for('PEOPLE_FOR_ISSUE_ASSIGNMENT', project_id, issue_id)
         
     | 
| 
      
 89 
     | 
    
         
            +
                end
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
                #Create Issue
         
     | 
| 
      
 92 
     | 
    
         
            +
                # project_id - project id
         
     | 
| 
      
 93 
     | 
    
         
            +
                # title - required title.
         
     | 
| 
      
 94 
     | 
    
         
            +
                # priority_id - priority levels
         
     | 
| 
      
 95 
     | 
    
         
            +
                # resolver_id - person assigned to solve this issue
         
     | 
| 
      
 96 
     | 
    
         
            +
                # tester_id - person assigned to test and verify if a issue is
         
     | 
| 
      
 97 
     | 
    
         
            +
                # resolved
         
     | 
| 
      
 98 
     | 
    
         
            +
                # description - optional description of the issue
         
     | 
| 
      
 99 
     | 
    
         
            +
                # tags - a string of tags delimited by comma
         
     | 
| 
      
 100 
     | 
    
         
            +
                # watcher_id - a string of people's id delimited by comma
         
     | 
| 
      
 101 
     | 
    
         
            +
                # attachments - list of file paths
         
     | 
| 
      
 102 
     | 
    
         
            +
                def create_issue( project_id, title, priority_id, resolver_id, tester_id, options={})
         
     | 
| 
      
 103 
     | 
    
         
            +
                  description=options[:description]
         
     | 
| 
      
 104 
     | 
    
         
            +
                  tags=options[:tags]
         
     | 
| 
      
 105 
     | 
    
         
            +
                  watcher_id=options[:watcher_id]
         
     | 
| 
      
 106 
     | 
    
         
            +
                  attachments=options[:attachments]
         
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
      
 108 
     | 
    
         
            +
                  data = {
         
     | 
| 
      
 109 
     | 
    
         
            +
                    'title' => title,
         
     | 
| 
      
 110 
     | 
    
         
            +
                    'priority_level_id' => priority_id,
         
     | 
| 
      
 111 
     | 
    
         
            +
                    'resolver_id' => resolver_id,
         
     | 
| 
      
 112 
     | 
    
         
            +
                    'tester_id' => tester_id,
         
     | 
| 
      
 113 
     | 
    
         
            +
                  }
         
     | 
| 
      
 114 
     | 
    
         
            +
             
     | 
| 
      
 115 
     | 
    
         
            +
                  data['description'] = description if description
         
     | 
| 
      
 116 
     | 
    
         
            +
                  data['tags'] = tags if tags
         
     | 
| 
      
 117 
     | 
    
         
            +
                  data['watcher_ids'] = watcher_id if watcher_id
         
     | 
| 
      
 118 
     | 
    
         
            +
             
     | 
| 
      
 119 
     | 
    
         
            +
                  params = {:data => data, :update => false, :post => true}
         
     | 
| 
      
 120 
     | 
    
         
            +
                  params[:attachments] = attachments if attachments
         
     | 
| 
      
 121 
     | 
    
         
            +
                  api Constant.url_for('CREATE_ISSUE', project_id), params
         
     | 
| 
      
 122 
     | 
    
         
            +
                  !result.empty? ? result["IssueID"] : nil
         
     | 
| 
      
 123 
     | 
    
         
            +
                end
         
     | 
| 
      
 124 
     | 
    
         
            +
             
     | 
| 
      
 125 
     | 
    
         
            +
                #Create Comment on issue
         
     | 
| 
      
 126 
     | 
    
         
            +
                #project_id - project id
         
     | 
| 
      
 127 
     | 
    
         
            +
                #issue_id - issue id
         
     | 
| 
      
 128 
     | 
    
         
            +
                #comment - comment string
         
     | 
| 
      
 129 
     | 
    
         
            +
                #people_to_cc_ids - a string of people to be CCed on this comment,
         
     | 
| 
      
 130 
     | 
    
         
            +
                #delimited by comma
         
     | 
| 
      
 131 
     | 
    
         
            +
                #attachments - list of absolute file path.
         
     | 
| 
      
 132 
     | 
    
         
            +
                def create_comment(project_id, order_number, comment, options={})
         
     | 
| 
      
 133 
     | 
    
         
            +
                  people_to_cc_ids=options[:people_to_cc_ids]
         
     | 
| 
      
 134 
     | 
    
         
            +
                  attachments=options[:attachments]
         
     | 
| 
      
 135 
     | 
    
         
            +
             
     | 
| 
      
 136 
     | 
    
         
            +
                  data = {'comment' => comment}
         
     | 
| 
      
 137 
     | 
    
         
            +
                  data['people_to_cc_ids']= people_to_cc_ids if people_to_cc_ids
         
     | 
| 
      
 138 
     | 
    
         
            +
             
     | 
| 
      
 139 
     | 
    
         
            +
                  params = {:data => data, :update => false, :post => true}
         
     | 
| 
      
 140 
     | 
    
         
            +
                  params[:attachments] = attachments if attachments
         
     | 
| 
      
 141 
     | 
    
         
            +
                  api Constant.url_for('COMMENT', project_id, order_number), params
         
     | 
| 
      
 142 
     | 
    
         
            +
                  !result.empty? ? result["CommentURL"] : nil
         
     | 
| 
      
 143 
     | 
    
         
            +
                end
         
     | 
| 
      
 144 
     | 
    
         
            +
             
     | 
| 
      
 145 
     | 
    
         
            +
                #Update Issue
         
     | 
| 
      
 146 
     | 
    
         
            +
                # If you provide any parameters then the value you pass will be
         
     | 
| 
      
 147 
     | 
    
         
            +
                # used to update the issue. If you wish to keep the value that's
         
     | 
| 
      
 148 
     | 
    
         
            +
                # already on an issue, then do not provide the parameter in your
         
     | 
| 
      
 149 
     | 
    
         
            +
                # PUT data. Any value you provide, including tags, will overwrite
         
     | 
| 
      
 150 
     | 
    
         
            +
                # the existing values on the issue. If you wish to retain the
         
     | 
| 
      
 151 
     | 
    
         
            +
                # tags for an issue and update it by adding one new tag, then
         
     | 
| 
      
 152 
     | 
    
         
            +
                # you'll have to provide all of the existing tags as well as the
         
     | 
| 
      
 153 
     | 
    
         
            +
                # new tag in your tags parameter, for example.
         
     | 
| 
      
 154 
     | 
    
         
            +
             
     | 
| 
      
 155 
     | 
    
         
            +
                # project_id - project id
         
     | 
| 
      
 156 
     | 
    
         
            +
                # order_number - issue id
         
     | 
| 
      
 157 
     | 
    
         
            +
                # title - required title
         
     | 
| 
      
 158 
     | 
    
         
            +
                # priority_id - priority levels
         
     | 
| 
      
 159 
     | 
    
         
            +
                # resolver_id - person assigned to solve this issue
         
     | 
| 
      
 160 
     | 
    
         
            +
                # tester_id - person assigned to test and verify if a issue is
         
     | 
| 
      
 161 
     | 
    
         
            +
                # resolved
         
     | 
| 
      
 162 
     | 
    
         
            +
                # description - optional description of the issue
         
     | 
| 
      
 163 
     | 
    
         
            +
                # tags - a string of tags delimited by comma
         
     | 
| 
      
 164 
     | 
    
         
            +
                # state_id - a valid state that this issue can transition to
         
     | 
| 
      
 165 
     | 
    
         
            +
                # attachments - list of file paths
         
     | 
| 
      
 166 
     | 
    
         
            +
                def update_issue(project_id, order_number, options={})
         
     | 
| 
      
 167 
     | 
    
         
            +
                  title=options[:title]
         
     | 
| 
      
 168 
     | 
    
         
            +
                  priority_id=options[:priority_id]
         
     | 
| 
      
 169 
     | 
    
         
            +
                  resolver_id=options[:resolver_id]
         
     | 
| 
      
 170 
     | 
    
         
            +
                  tester_id=options[:tester_id]
         
     | 
| 
      
 171 
     | 
    
         
            +
                  description=options[:description]
         
     | 
| 
      
 172 
     | 
    
         
            +
                  tags=options[:tags]
         
     | 
| 
      
 173 
     | 
    
         
            +
                  state_id=options[:state_id]
         
     | 
| 
      
 174 
     | 
    
         
            +
                  attachments=options[:attachments]
         
     | 
| 
      
 175 
     | 
    
         
            +
             
     | 
| 
      
 176 
     | 
    
         
            +
                  data = {}
         
     | 
| 
      
 177 
     | 
    
         
            +
                  data['title'] = title if title
         
     | 
| 
      
 178 
     | 
    
         
            +
                  data['priority_level_id'] = priority_id if priority_id
         
     | 
| 
      
 179 
     | 
    
         
            +
                  data['resolver_id'] = resolver_id if resolver_id
         
     | 
| 
      
 180 
     | 
    
         
            +
             
     | 
| 
      
 181 
     | 
    
         
            +
                  data['tester_id'] = tester_id if tester_id
         
     | 
| 
      
 182 
     | 
    
         
            +
                  data['description'] = description if description
         
     | 
| 
      
 183 
     | 
    
         
            +
                  data['tags'] = tags if tags
         
     | 
| 
      
 184 
     | 
    
         
            +
                  data['state_id'] = state_id if state_id
         
     | 
| 
      
 185 
     | 
    
         
            +
             
     | 
| 
      
 186 
     | 
    
         
            +
                  params = {:update => true}
         
     | 
| 
      
 187 
     | 
    
         
            +
                  params[:data] = data unless data.empty?
         
     | 
| 
      
 188 
     | 
    
         
            +
                  params[:attachments] = attachments if attachments
         
     | 
| 
      
 189 
     | 
    
         
            +
                  api Constant.url_for('ISSUE', project_id, order_number), params
         
     | 
| 
      
 190 
     | 
    
         
            +
                  !result.empty? ? result["IssueURL"] : nil
         
     | 
| 
      
 191 
     | 
    
         
            +
                end
         
     | 
| 
      
 192 
     | 
    
         
            +
             
     | 
| 
      
 193 
     | 
    
         
            +
             
     | 
| 
      
 194 
     | 
    
         
            +
                private
         
     | 
| 
      
 195 
     | 
    
         
            +
             
     | 
| 
      
 196 
     | 
    
         
            +
                # Perform generic API calling
         
     | 
| 
      
 197 
     | 
    
         
            +
                #This is the base method for all IssueTracker API calls.
         
     | 
| 
      
 198 
     | 
    
         
            +
                # method_url - IssueTracker method URL
         
     | 
| 
      
 199 
     | 
    
         
            +
                # data - optional POST form data
         
     | 
| 
      
 200 
     | 
    
         
            +
                # attachemnts - optional list of file paths
         
     | 
| 
      
 201 
     | 
    
         
            +
                # update - flag to indicate if this is a PUT operation
         
     | 
| 
      
 202 
     | 
    
         
            +
                def api(method_url, options={})
         
     | 
| 
      
 203 
     | 
    
         
            +
                  data = options[:data]
         
     | 
| 
      
 204 
     | 
    
         
            +
                  attachments = options[:attachments]
         
     | 
| 
      
 205 
     | 
    
         
            +
                  update = options.has_key?(:update) ? options[:update] : false
         
     | 
| 
      
 206 
     | 
    
         
            +
                  post = options.has_key?(:post) ? options[:post] : false
         
     | 
| 
      
 207 
     | 
    
         
            +
             
     | 
| 
      
 208 
     | 
    
         
            +
                  @response = nil
         
     | 
| 
      
 209 
     | 
    
         
            +
                  files = {}
         
     | 
| 
      
 210 
     | 
    
         
            +
                  request_method = nil
         
     | 
| 
      
 211 
     | 
    
         
            +
             
     | 
| 
      
 212 
     | 
    
         
            +
                  if attachments
         
     | 
| 
      
 213 
     | 
    
         
            +
                    debug { "attachments; using post" }
         
     | 
| 
      
 214 
     | 
    
         
            +
                    request_method = :post
         
     | 
| 
      
 215 
     | 
    
         
            +
                    attachments.each_with_index do |attachment, index|
         
     | 
| 
      
 216 
     | 
    
         
            +
                      files["attachment-#{index}"] = attachment
         
     | 
| 
      
 217 
     | 
    
         
            +
                    end
         
     | 
| 
      
 218 
     | 
    
         
            +
                  else
         
     | 
| 
      
 219 
     | 
    
         
            +
                    request_method = :get
         
     | 
| 
      
 220 
     | 
    
         
            +
                  end
         
     | 
| 
      
 221 
     | 
    
         
            +
             
     | 
| 
      
 222 
     | 
    
         
            +
                  if update
         
     | 
| 
      
 223 
     | 
    
         
            +
                    debug { "using put" }
         
     | 
| 
      
 224 
     | 
    
         
            +
                    request_method = :put
         
     | 
| 
      
 225 
     | 
    
         
            +
                  end
         
     | 
| 
      
 226 
     | 
    
         
            +
             
     | 
| 
      
 227 
     | 
    
         
            +
                  if post
         
     | 
| 
      
 228 
     | 
    
         
            +
                    debug { "using post" }
         
     | 
| 
      
 229 
     | 
    
         
            +
                    request_method = :post
         
     | 
| 
      
 230 
     | 
    
         
            +
                  end
         
     | 
| 
      
 231 
     | 
    
         
            +
             
     | 
| 
      
 232 
     | 
    
         
            +
                  params = { :debug => _debug }
         
     | 
| 
      
 233 
     | 
    
         
            +
                  params[:data] = data if data
         
     | 
| 
      
 234 
     | 
    
         
            +
                  params[:files] = files unless files.empty?
         
     | 
| 
      
 235 
     | 
    
         
            +
             
     | 
| 
      
 236 
     | 
    
         
            +
                  @response = _http_helper.send(request_method, method_url, params)
         
     | 
| 
      
 237 
     | 
    
         
            +
                  return result
         
     | 
| 
      
 238 
     | 
    
         
            +
                rescue Exception => e
         
     | 
| 
      
 239 
     | 
    
         
            +
                  warn e.message
         
     | 
| 
      
 240 
     | 
    
         
            +
                  warn e.backtrace.inspect
         
     | 
| 
      
 241 
     | 
    
         
            +
                  return ""
         
     | 
| 
      
 242 
     | 
    
         
            +
                end
         
     | 
| 
      
 243 
     | 
    
         
            +
             
     | 
| 
      
 244 
     | 
    
         
            +
                def debug
         
     | 
| 
      
 245 
     | 
    
         
            +
                  puts(yield) if _debug && block_given?
         
     | 
| 
      
 246 
     | 
    
         
            +
                end
         
     | 
| 
      
 247 
     | 
    
         
            +
              end
         
     | 
| 
      
 248 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,78 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # Takes a hash of file-key and file-name and returns a string of text
         
     | 
| 
      
 2 
     | 
    
         
            +
            # formatted to be sent as a multipart form post.
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            require 'mime/types'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'cgi'
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            module DoneDone
         
     | 
| 
      
 9 
     | 
    
         
            +
              module Multipart
         
     | 
| 
      
 10 
     | 
    
         
            +
                VERSION = "1.0.0" unless const_defined?(:VERSION)
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                # Formats a given hash as a multipart form post
         
     | 
| 
      
 13 
     | 
    
         
            +
                # If determine if the params are Files or Strings and process
         
     | 
| 
      
 14 
     | 
    
         
            +
                # appropriately
         
     | 
| 
      
 15 
     | 
    
         
            +
                class Post
         
     | 
| 
      
 16 
     | 
    
         
            +
                  # We have to pretend like we're a web browser...
         
     | 
| 
      
 17 
     | 
    
         
            +
                  USERAGENT = "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/523.10.6 (KHTML, like Gecko) Version/3.0.4 Safari/523.10.6" unless const_defined?(:USERAGENT)
         
     | 
| 
      
 18 
     | 
    
         
            +
                  BOUNDARY = '--JTMultiPart' + rand(1000000).to_s + 'ZZZZZ' unless const_defined?(:BOUNDARY)
         
     | 
| 
      
 19 
     | 
    
         
            +
                  CONTENT_TYPE = "multipart/form-data; boundary=#{ BOUNDARY }" unless const_defined?(:CONTENT_TYPE)
         
     | 
| 
      
 20 
     | 
    
         
            +
                  #HEADER = { "Content-Type" => CONTENT_TYPE, "User-Agent" => USERAGENT } unless const_defined?(:HEADER)
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                  def self.prepare_query(params)
         
     | 
| 
      
 23 
     | 
    
         
            +
                    fp = []
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                    params.each do |k, v|
         
     | 
| 
      
 26 
     | 
    
         
            +
                      if File.exists?(v) # must be a file
         
     | 
| 
      
 27 
     | 
    
         
            +
                        path = File.path(v)
         
     | 
| 
      
 28 
     | 
    
         
            +
                        content = File.binread(v)
         
     | 
| 
      
 29 
     | 
    
         
            +
                        fp.push(FileParam.new(k, path, content))
         
     | 
| 
      
 30 
     | 
    
         
            +
                      else # must be a string
         
     | 
| 
      
 31 
     | 
    
         
            +
                        fp.push(StringParam.new(k, v))
         
     | 
| 
      
 32 
     | 
    
         
            +
                      end
         
     | 
| 
      
 33 
     | 
    
         
            +
                    end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                    # Assemble the request body using the special multipart format
         
     | 
| 
      
 36 
     | 
    
         
            +
                    query = fp.collect {|p| "--" + BOUNDARY + "\r\n" + p.to_multipart }.join("")  + "--" + BOUNDARY + "--"
         
     | 
| 
      
 37 
     | 
    
         
            +
                    return query, CONTENT_TYPE, USERAGENT
         
     | 
| 
      
 38 
     | 
    
         
            +
                  end
         
     | 
| 
      
 39 
     | 
    
         
            +
                end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                private
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                class StringParam
         
     | 
| 
      
 45 
     | 
    
         
            +
                  attr_accessor :k, :v
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                  def initialize(k, v)
         
     | 
| 
      
 48 
     | 
    
         
            +
                    @k = k
         
     | 
| 
      
 49 
     | 
    
         
            +
                    @v = v
         
     | 
| 
      
 50 
     | 
    
         
            +
                  end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                  def to_multipart
         
     | 
| 
      
 53 
     | 
    
         
            +
                    return "Content-Disposition: form-data; name=\"#{CGI::escape(k)}\"\r\n\r\n#{v}\r\n"
         
     | 
| 
      
 54 
     | 
    
         
            +
                  end
         
     | 
| 
      
 55 
     | 
    
         
            +
                end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                # Formats the contents of a file for inclusion with a multipart
         
     | 
| 
      
 58 
     | 
    
         
            +
                # form post
         
     | 
| 
      
 59 
     | 
    
         
            +
                class FileParam
         
     | 
| 
      
 60 
     | 
    
         
            +
                  attr_accessor :k, :filename, :content
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                  def initialize(k, filename, content)
         
     | 
| 
      
 63 
     | 
    
         
            +
                    @k = k
         
     | 
| 
      
 64 
     | 
    
         
            +
                    @filename = filename
         
     | 
| 
      
 65 
     | 
    
         
            +
                    @content = content
         
     | 
| 
      
 66 
     | 
    
         
            +
                  end
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                  def to_multipart
         
     | 
| 
      
 69 
     | 
    
         
            +
                    # If we can tell the possible mime-type from the filename, use the
         
     | 
| 
      
 70 
     | 
    
         
            +
                    # first in the list; otherwise, use "application/octet-stream"
         
     | 
| 
      
 71 
     | 
    
         
            +
                    mime_type = MIME::Types.type_for(filename)[0] || MIME::Types["application/octet-stream"][0]
         
     | 
| 
      
 72 
     | 
    
         
            +
                    return "Content-Disposition: form-data; name=\"#{CGI::escape(k)}\"; filename=\"#{ filename }\"\r\n" +
         
     | 
| 
      
 73 
     | 
    
         
            +
                      "Content-Transfer-Encoding: binary\r\n" +
         
     | 
| 
      
 74 
     | 
    
         
            +
                      "Content-Type: #{ mime_type.simplified }\r\n\r\n#{ content }\r\n"
         
     | 
| 
      
 75 
     | 
    
         
            +
                  end
         
     | 
| 
      
 76 
     | 
    
         
            +
                end
         
     | 
| 
      
 77 
     | 
    
         
            +
              end
         
     | 
| 
      
 78 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,17 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'spec_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            describe DoneDone::Constant do
         
     | 
| 
      
 4 
     | 
    
         
            +
              describe ".url_for" do
         
     | 
| 
      
 5 
     | 
    
         
            +
                context 'valid args' do
         
     | 
| 
      
 6 
     | 
    
         
            +
                  it "generates url with format string" do
         
     | 
| 
      
 7 
     | 
    
         
            +
                    expect(DoneDone::Constant.url_for('PEOPLE_IN_PROJECT')).to eq(DoneDone::Constant::PEOPLE_IN_PROJECT)
         
     | 
| 
      
 8 
     | 
    
         
            +
                    expect(DoneDone::Constant.url_for('PEOPLE_IN_PROJECT', '%s')).to eq(DoneDone::Constant::PEOPLE_IN_PROJECT)
         
     | 
| 
      
 9 
     | 
    
         
            +
                  end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                  it "generates url without format string" do
         
     | 
| 
      
 12 
     | 
    
         
            +
                    expect(DoneDone::Constant.url_for('PROJECTS_WITH_ISSUES')).to eq(DoneDone::Constant::PROJECTS_WITH_ISSUES)
         
     | 
| 
      
 13 
     | 
    
         
            +
                    expect(DoneDone::Constant.url_for('PROJECTS_WITH_ISSUES', 'bogus_arg1')).to eq(DoneDone::Constant::PROJECTS_WITH_ISSUES)
         
     | 
| 
      
 14 
     | 
    
         
            +
                  end
         
     | 
| 
      
 15 
     | 
    
         
            +
                end
         
     | 
| 
      
 16 
     | 
    
         
            +
              end
         
     | 
| 
      
 17 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,101 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'spec_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            describe DoneDone::Http do
         
     | 
| 
      
 4 
     | 
    
         
            +
              class BogusNetHttp
         
     | 
| 
      
 5 
     | 
    
         
            +
                attr_reader :host, :port, :use_ssl
         
     | 
| 
      
 6 
     | 
    
         
            +
                attr_accessor :ssl_version, :verify_mode
         
     | 
| 
      
 7 
     | 
    
         
            +
                def initialize(host, port)
         
     | 
| 
      
 8 
     | 
    
         
            +
                  @host = host
         
     | 
| 
      
 9 
     | 
    
         
            +
                  @port = port
         
     | 
| 
      
 10 
     | 
    
         
            +
                  clear
         
     | 
| 
      
 11 
     | 
    
         
            +
                end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                def clear
         
     | 
| 
      
 14 
     | 
    
         
            +
                  @use_ssl = false
         
     | 
| 
      
 15 
     | 
    
         
            +
                  @verify_mode = nil
         
     | 
| 
      
 16 
     | 
    
         
            +
                  @ssl_version = nil
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                def use_ssl=(bool)
         
     | 
| 
      
 20 
     | 
    
         
            +
                  @use_ssl = !!bool
         
     | 
| 
      
 21 
     | 
    
         
            +
                end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                def request(request_object)
         
     | 
| 
      
 24 
     | 
    
         
            +
                  @request = request_object
         
     | 
| 
      
 25 
     | 
    
         
            +
                end
         
     | 
| 
      
 26 
     | 
    
         
            +
              end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
              let(:net_http_class) { BogusNetHttp }
         
     | 
| 
      
 29 
     | 
    
         
            +
              let(:domain) { "domain" }
         
     | 
| 
      
 30 
     | 
    
         
            +
              let(:username) { "username" }
         
     | 
| 
      
 31 
     | 
    
         
            +
              let(:password) { "password" }
         
     | 
| 
      
 32 
     | 
    
         
            +
              let(:new_options) { {:http_class => net_http_class} }
         
     | 
| 
      
 33 
     | 
    
         
            +
              let(:new_args) { [domain, username, password, new_options] }
         
     | 
| 
      
 34 
     | 
    
         
            +
              let(:donedone_http_object) { DoneDone::Http.new(*new_args) }
         
     | 
| 
      
 35 
     | 
    
         
            +
              let(:request_methods) { [:get, :put, :post] }
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
              describe "init" do
         
     | 
| 
      
 38 
     | 
    
         
            +
                context 'invalid args' do
         
     | 
| 
      
 39 
     | 
    
         
            +
                  it "raises an Exception for 0-2 args" do
         
     | 
| 
      
 40 
     | 
    
         
            +
                    expect { DoneDone::Http.new }.to raise_error()
         
     | 
| 
      
 41 
     | 
    
         
            +
                    expect { DoneDone::Http.new(domain) }.to raise_error()
         
     | 
| 
      
 42 
     | 
    
         
            +
                    expect { DoneDone::Http.new(domain, username) }.to raise_error()
         
     | 
| 
      
 43 
     | 
    
         
            +
                  end
         
     | 
| 
      
 44 
     | 
    
         
            +
                  it "raises an Exception for >4 args" do
         
     | 
| 
      
 45 
     | 
    
         
            +
                    expect { DoneDone::Http.new(domain, username, password, {}, :extra1) }.to raise_error()
         
     | 
| 
      
 46 
     | 
    
         
            +
                  end
         
     | 
| 
      
 47 
     | 
    
         
            +
                end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                context 'valid args' do
         
     | 
| 
      
 50 
     | 
    
         
            +
                  it "requires 3-4 args" do
         
     | 
| 
      
 51 
     | 
    
         
            +
                    expect { DoneDone::Http.new(domain, username, password) }.to_not raise_error()
         
     | 
| 
      
 52 
     | 
    
         
            +
                    expect { DoneDone::Http.new(domain, username, password, {}) }.to_not raise_error()
         
     | 
| 
      
 53 
     | 
    
         
            +
                  end
         
     | 
| 
      
 54 
     | 
    
         
            +
                end
         
     | 
| 
      
 55 
     | 
    
         
            +
              end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
              describe "request(s)" do
         
     | 
| 
      
 58 
     | 
    
         
            +
                let(:method_url) { "method_url" }
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                context 'invalid args' do
         
     | 
| 
      
 61 
     | 
    
         
            +
                  it "will raise an Exception for 0 args" do
         
     | 
| 
      
 62 
     | 
    
         
            +
                    request_methods.each do |method|
         
     | 
| 
      
 63 
     | 
    
         
            +
                      expect { donedone_http_object.send(method) }.to raise_error
         
     | 
| 
      
 64 
     | 
    
         
            +
                    end
         
     | 
| 
      
 65 
     | 
    
         
            +
                  end
         
     | 
| 
      
 66 
     | 
    
         
            +
                  it "will raise an Exception for >2 args" do
         
     | 
| 
      
 67 
     | 
    
         
            +
                    request_methods.each do |method|
         
     | 
| 
      
 68 
     | 
    
         
            +
                      expect { donedone_http_object.send(method, method_url, {}, :extra1) }.to raise_error
         
     | 
| 
      
 69 
     | 
    
         
            +
                    end
         
     | 
| 
      
 70 
     | 
    
         
            +
                  end
         
     | 
| 
      
 71 
     | 
    
         
            +
                end
         
     | 
| 
      
 72 
     | 
    
         
            +
                context 'valid args' do
         
     | 
| 
      
 73 
     | 
    
         
            +
                  let(:ssl_port) { 443 }
         
     | 
| 
      
 74 
     | 
    
         
            +
                  it "will not raise an Exception for 1-2 args" do
         
     | 
| 
      
 75 
     | 
    
         
            +
                    request_methods.each do |method|
         
     | 
| 
      
 76 
     | 
    
         
            +
                      expect { donedone_http_object.send(method, method_url) }.to_not raise_error
         
     | 
| 
      
 77 
     | 
    
         
            +
                      expect { donedone_http_object.send(method, method_url, {}) }.to_not raise_error
         
     | 
| 
      
 78 
     | 
    
         
            +
                    end
         
     | 
| 
      
 79 
     | 
    
         
            +
                  end
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                  # a bit fragile: specific to Net::HTTP
         
     | 
| 
      
 82 
     | 
    
         
            +
                  it "sets-up a proper http object for :get" do
         
     | 
| 
      
 83 
     | 
    
         
            +
                    expect(donedone_http_object.host).to start_with(domain)
         
     | 
| 
      
 84 
     | 
    
         
            +
                    net_http_obj = net_http_class.new(donedone_http_object.host, ssl_port)
         
     | 
| 
      
 85 
     | 
    
         
            +
                    net_http_class.should_receive(:new).exactly(request_methods.length).times.with(donedone_http_object.host, ssl_port).and_return(net_http_obj)
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
                    request_methods.each do |method|
         
     | 
| 
      
 88 
     | 
    
         
            +
                      expect(net_http_obj.use_ssl).to eq(false)
         
     | 
| 
      
 89 
     | 
    
         
            +
                      expect(net_http_obj.verify_mode).to eq(nil)
         
     | 
| 
      
 90 
     | 
    
         
            +
                      expect(net_http_obj.ssl_version).to eq(nil)
         
     | 
| 
      
 91 
     | 
    
         
            +
                      donedone_http_object.send(method, method_url)
         
     | 
| 
      
 92 
     | 
    
         
            +
                      expect(net_http_obj.use_ssl).to eq(true)
         
     | 
| 
      
 93 
     | 
    
         
            +
                      expect(net_http_obj.verify_mode).to eq(DoneDone::Constant::SSL_VERIFY_MODE)
         
     | 
| 
      
 94 
     | 
    
         
            +
                      expect(net_http_obj.ssl_version).to eq(DoneDone::Constant::SSL_VERSION)
         
     | 
| 
      
 95 
     | 
    
         
            +
                      donedone_http_object.reset
         
     | 
| 
      
 96 
     | 
    
         
            +
                      net_http_obj.clear
         
     | 
| 
      
 97 
     | 
    
         
            +
                    end
         
     | 
| 
      
 98 
     | 
    
         
            +
                  end
         
     | 
| 
      
 99 
     | 
    
         
            +
                end
         
     | 
| 
      
 100 
     | 
    
         
            +
              end
         
     | 
| 
      
 101 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,164 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'spec_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            describe DoneDone::IssueTracker do
         
     | 
| 
      
 4 
     | 
    
         
            +
              let(:bogus_http_helper) { Object.new }
         
     | 
| 
      
 5 
     | 
    
         
            +
              let(:http_helper) { bogus_http_helper }
         
     | 
| 
      
 6 
     | 
    
         
            +
              let(:domain) { :domain }
         
     | 
| 
      
 7 
     | 
    
         
            +
              let(:username) { :username }
         
     | 
| 
      
 8 
     | 
    
         
            +
              let(:password) { :password }
         
     | 
| 
      
 9 
     | 
    
         
            +
              let(:http_helper_options) { {:debug=>false} }
         
     | 
| 
      
 10 
     | 
    
         
            +
              let(:issue_tracker) { DoneDone::IssueTracker.new(domain, username, password, :http_helper => http_helper) }
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
              describe "init" do
         
     | 
| 
      
 13 
     | 
    
         
            +
                context 'invalid args' do
         
     | 
| 
      
 14 
     | 
    
         
            +
                  it "raises an Exception for 0-1 args" do
         
     | 
| 
      
 15 
     | 
    
         
            +
                    expect { DoneDone::IssueTracker.new }.to raise_error()
         
     | 
| 
      
 16 
     | 
    
         
            +
                    expect { DoneDone::IssueTracker.new(domain) }.to raise_error()
         
     | 
| 
      
 17 
     | 
    
         
            +
                  end
         
     | 
| 
      
 18 
     | 
    
         
            +
                  it "raises an Exception for >4 args" do
         
     | 
| 
      
 19 
     | 
    
         
            +
                    expect { DoneDone::IssueTracker.new(domain, username, password, {}, :extra1) }.to raise_error()
         
     | 
| 
      
 20 
     | 
    
         
            +
                  end
         
     | 
| 
      
 21 
     | 
    
         
            +
                end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                context 'valid args' do
         
     | 
| 
      
 24 
     | 
    
         
            +
                  it "requires 2-4 args" do
         
     | 
| 
      
 25 
     | 
    
         
            +
                    expect { DoneDone::IssueTracker.new(domain, username) }.to_not raise_error()
         
     | 
| 
      
 26 
     | 
    
         
            +
                    expect { DoneDone::IssueTracker.new(domain, username, password) }.to_not raise_error()
         
     | 
| 
      
 27 
     | 
    
         
            +
                    expect { DoneDone::IssueTracker.new(domain, username, password, {}) }.to_not raise_error()
         
     | 
| 
      
 28 
     | 
    
         
            +
                  end
         
     | 
| 
      
 29 
     | 
    
         
            +
                end
         
     | 
| 
      
 30 
     | 
    
         
            +
              end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
              describe "methods" do
         
     | 
| 
      
 33 
     | 
    
         
            +
                let(:expected_api_methods) { [ :projects, :priority_levels, :people_in_project, :issues_in_project, :issue_exist?, :potential_statuses_for_issue, :issue, :people_for_issue_assignment, :create_issue, :create_comment, :update_issue ] }
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                let(:actual_helper_methods) { DoneDone::IssueTracker::HELPER_METHODS }
         
     | 
| 
      
 36 
     | 
    
         
            +
                let(:actual_api_methods) { DoneDone::IssueTracker.api_methods }
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                it "distinguises its api- and helper-methods" do
         
     | 
| 
      
 39 
     | 
    
         
            +
                  expect(actual_api_methods).to_not include(actual_helper_methods)
         
     | 
| 
      
 40 
     | 
    
         
            +
                end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                it "knows its api methods" do
         
     | 
| 
      
 43 
     | 
    
         
            +
                  expect(DoneDone::IssueTracker.api_methods).to eq(expected_api_methods)
         
     | 
| 
      
 44 
     | 
    
         
            +
                end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                it "responds to its expected-helper and -api methods" do
         
     | 
| 
      
 47 
     | 
    
         
            +
                  (actual_helper_methods + actual_api_methods).each do |expected_method|
         
     | 
| 
      
 48 
     | 
    
         
            +
                    expect(issue_tracker).to respond_to(expected_method)
         
     | 
| 
      
 49 
     | 
    
         
            +
                  end
         
     | 
| 
      
 50 
     | 
    
         
            +
                end
         
     | 
| 
      
 51 
     | 
    
         
            +
              end
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
              describe "api-requests" do
         
     | 
| 
      
 54 
     | 
    
         
            +
                it "requests all projects" do
         
     | 
| 
      
 55 
     | 
    
         
            +
                  http_helper.should_receive(:get).with( DoneDone::Constant::PROJECTS, http_helper_options )
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                  issue_tracker.projects
         
     | 
| 
      
 58 
     | 
    
         
            +
                end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                it "requests all projects with their issues" do
         
     | 
| 
      
 61 
     | 
    
         
            +
                  http_helper.should_receive(:get).with( DoneDone::Constant::PROJECTS_WITH_ISSUES, http_helper_options)
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                  issue_tracker.projects(true)
         
     | 
| 
      
 64 
     | 
    
         
            +
                end
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                it "requests all priority_levels" do
         
     | 
| 
      
 67 
     | 
    
         
            +
                  http_helper.should_receive(:get).with( DoneDone::Constant::PRIORITY_LEVELS, http_helper_options)
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
                  issue_tracker.priority_levels
         
     | 
| 
      
 70 
     | 
    
         
            +
                end
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                it "requests all people_in_project" do
         
     | 
| 
      
 73 
     | 
    
         
            +
                  project_id = 1
         
     | 
| 
      
 74 
     | 
    
         
            +
                  http_helper.should_receive(:get).with( DoneDone::Constant.url_for('PEOPLE_IN_PROJECT', project_id), http_helper_options)
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
                  issue_tracker.people_in_project(project_id)
         
     | 
| 
      
 77 
     | 
    
         
            +
                end
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
                it "requests all issues_in_project" do
         
     | 
| 
      
 80 
     | 
    
         
            +
                  project_id = 1
         
     | 
| 
      
 81 
     | 
    
         
            +
                  http_helper.should_receive(:get).with( DoneDone::Constant.url_for('ISSUES_IN_PROJECT', project_id), http_helper_options)
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
                  issue_tracker.issues_in_project(project_id)
         
     | 
| 
      
 84 
     | 
    
         
            +
                end
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
                it "requests if an issue exists for a project" do
         
     | 
| 
      
 87 
     | 
    
         
            +
                  project_id = 1
         
     | 
| 
      
 88 
     | 
    
         
            +
                  issue_order_number = 1
         
     | 
| 
      
 89 
     | 
    
         
            +
                  http_helper.should_receive(:get).with( DoneDone::Constant.url_for('DOES_ISSUE_EXIST', project_id, issue_order_number), http_helper_options)
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
                  issue_tracker.issue_exist?(project_id, issue_order_number)
         
     | 
| 
      
 92 
     | 
    
         
            +
                end
         
     | 
| 
      
 93 
     | 
    
         
            +
             
     | 
| 
      
 94 
     | 
    
         
            +
                it "requests status for a project's issue" do
         
     | 
| 
      
 95 
     | 
    
         
            +
                  project_id = 1
         
     | 
| 
      
 96 
     | 
    
         
            +
                  issue_order_number = 1
         
     | 
| 
      
 97 
     | 
    
         
            +
                  http_helper.should_receive(:get).with( DoneDone::Constant.url_for('POTENTIAL_STATUSES_FOR_ISSUE', project_id, issue_order_number), http_helper_options)
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
                  issue_tracker.potential_statuses_for_issue(project_id, issue_order_number)
         
     | 
| 
      
 100 
     | 
    
         
            +
                end
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
      
 102 
     | 
    
         
            +
                it "requests a project's issue's details" do
         
     | 
| 
      
 103 
     | 
    
         
            +
                  project_id = 1
         
     | 
| 
      
 104 
     | 
    
         
            +
                  issue_order_number = 1
         
     | 
| 
      
 105 
     | 
    
         
            +
                  http_helper.should_receive(:get).with( DoneDone::Constant.url_for('ISSUE', project_id, issue_order_number), http_helper_options)
         
     | 
| 
      
 106 
     | 
    
         
            +
             
     | 
| 
      
 107 
     | 
    
         
            +
                  issue_tracker.issue(project_id, issue_order_number)
         
     | 
| 
      
 108 
     | 
    
         
            +
                end
         
     | 
| 
      
 109 
     | 
    
         
            +
             
     | 
| 
      
 110 
     | 
    
         
            +
                it "requests people for issue assignment" do
         
     | 
| 
      
 111 
     | 
    
         
            +
                  project_id = 1
         
     | 
| 
      
 112 
     | 
    
         
            +
                  issue_order_number = 1
         
     | 
| 
      
 113 
     | 
    
         
            +
                  http_helper.should_receive(:get).with( DoneDone::Constant.url_for('PEOPLE_FOR_ISSUE_ASSIGNMENT', project_id, issue_order_number), http_helper_options)
         
     | 
| 
      
 114 
     | 
    
         
            +
             
     | 
| 
      
 115 
     | 
    
         
            +
                  issue_tracker.people_for_issue_assignment(project_id, issue_order_number)
         
     | 
| 
      
 116 
     | 
    
         
            +
                end
         
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
      
 118 
     | 
    
         
            +
                it "requests to create an issue" do
         
     | 
| 
      
 119 
     | 
    
         
            +
                  project_id = 1
         
     | 
| 
      
 120 
     | 
    
         
            +
                  title = 'required title'
         
     | 
| 
      
 121 
     | 
    
         
            +
                  priority_level_id = 2 # required
         
     | 
| 
      
 122 
     | 
    
         
            +
                  resolver_id = 2 # required
         
     | 
| 
      
 123 
     | 
    
         
            +
                  tester_id = 2 # required
         
     | 
| 
      
 124 
     | 
    
         
            +
             
     | 
| 
      
 125 
     | 
    
         
            +
                  data = {
         
     | 
| 
      
 126 
     | 
    
         
            +
                    'title' => title,
         
     | 
| 
      
 127 
     | 
    
         
            +
                    'priority_level_id' => priority_level_id,
         
     | 
| 
      
 128 
     | 
    
         
            +
                    'resolver_id' => resolver_id,
         
     | 
| 
      
 129 
     | 
    
         
            +
                    'tester_id' => tester_id,
         
     | 
| 
      
 130 
     | 
    
         
            +
                  }
         
     | 
| 
      
 131 
     | 
    
         
            +
             
     | 
| 
      
 132 
     | 
    
         
            +
                  options = http_helper_options.merge(:data => data)
         
     | 
| 
      
 133 
     | 
    
         
            +
                  http_helper.should_receive(:post).with( DoneDone::Constant.url_for('CREATE_ISSUE', project_id), options)
         
     | 
| 
      
 134 
     | 
    
         
            +
             
     | 
| 
      
 135 
     | 
    
         
            +
                  issue_tracker.create_issue(project_id, title, priority_level_id, resolver_id, tester_id)
         
     | 
| 
      
 136 
     | 
    
         
            +
                end
         
     | 
| 
      
 137 
     | 
    
         
            +
             
     | 
| 
      
 138 
     | 
    
         
            +
                # todo: test for passing file upload(s)
         
     | 
| 
      
 139 
     | 
    
         
            +
                it "requests to create a comment for a project's issue" do
         
     | 
| 
      
 140 
     | 
    
         
            +
                  project_id = 1
         
     | 
| 
      
 141 
     | 
    
         
            +
                  issue_order_number = 1
         
     | 
| 
      
 142 
     | 
    
         
            +
                  comment = 'required comment'
         
     | 
| 
      
 143 
     | 
    
         
            +
             
     | 
| 
      
 144 
     | 
    
         
            +
                  data = { 'comment' => comment }
         
     | 
| 
      
 145 
     | 
    
         
            +
             
     | 
| 
      
 146 
     | 
    
         
            +
                  options = http_helper_options.merge(:data => data)
         
     | 
| 
      
 147 
     | 
    
         
            +
                  http_helper.should_receive(:post).with( DoneDone::Constant.url_for('COMMENT', project_id, issue_order_number), options)
         
     | 
| 
      
 148 
     | 
    
         
            +
             
     | 
| 
      
 149 
     | 
    
         
            +
                  issue_tracker.create_comment(project_id, issue_order_number, comment)
         
     | 
| 
      
 150 
     | 
    
         
            +
                end
         
     | 
| 
      
 151 
     | 
    
         
            +
             
     | 
| 
      
 152 
     | 
    
         
            +
                it "requests to update a project's issue" do
         
     | 
| 
      
 153 
     | 
    
         
            +
                  project_id = 1
         
     | 
| 
      
 154 
     | 
    
         
            +
                  issue_order_number = 1
         
     | 
| 
      
 155 
     | 
    
         
            +
             
     | 
| 
      
 156 
     | 
    
         
            +
                  options = http_helper_options
         
     | 
| 
      
 157 
     | 
    
         
            +
                  http_helper.should_receive(:put).with( DoneDone::Constant.url_for('ISSUE', project_id, issue_order_number), options)
         
     | 
| 
      
 158 
     | 
    
         
            +
             
     | 
| 
      
 159 
     | 
    
         
            +
                  issue_tracker.update_issue(project_id, issue_order_number, options)
         
     | 
| 
      
 160 
     | 
    
         
            +
                end
         
     | 
| 
      
 161 
     | 
    
         
            +
             
     | 
| 
      
 162 
     | 
    
         
            +
              end
         
     | 
| 
      
 163 
     | 
    
         
            +
             
     | 
| 
      
 164 
     | 
    
         
            +
            end
         
     | 
    
        data/spec/spec_helper.rb
    ADDED
    
    
    
        metadata
    ADDED
    
    | 
         @@ -0,0 +1,95 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            --- !ruby/object:Gem::Specification
         
     | 
| 
      
 2 
     | 
    
         
            +
            name: donedone
         
     | 
| 
      
 3 
     | 
    
         
            +
            version: !ruby/object:Gem::Version
         
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.0.4
         
     | 
| 
      
 5 
     | 
    
         
            +
            platform: ruby
         
     | 
| 
      
 6 
     | 
    
         
            +
            authors:
         
     | 
| 
      
 7 
     | 
    
         
            +
            - Jonathan Thomas
         
     | 
| 
      
 8 
     | 
    
         
            +
            autorequire: 
         
     | 
| 
      
 9 
     | 
    
         
            +
            bindir: bin
         
     | 
| 
      
 10 
     | 
    
         
            +
            cert_chain: []
         
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2013-11-04 00:00:00.000000000 Z
         
     | 
| 
      
 12 
     | 
    
         
            +
            dependencies:
         
     | 
| 
      
 13 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 14 
     | 
    
         
            +
              name: mime-types
         
     | 
| 
      
 15 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 16 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 17 
     | 
    
         
            +
                - - ~>
         
     | 
| 
      
 18 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 19 
     | 
    
         
            +
                    version: '2.0'
         
     | 
| 
      
 20 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 21 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 22 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 23 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 24 
     | 
    
         
            +
                - - ~>
         
     | 
| 
      
 25 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 26 
     | 
    
         
            +
                    version: '2.0'
         
     | 
| 
      
 27 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 28 
     | 
    
         
            +
              name: rspec
         
     | 
| 
      
 29 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 30 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 31 
     | 
    
         
            +
                - - ~>
         
     | 
| 
      
 32 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 33 
     | 
    
         
            +
                    version: 2.14.0
         
     | 
| 
      
 34 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 35 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 36 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 37 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 38 
     | 
    
         
            +
                - - ~>
         
     | 
| 
      
 39 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 40 
     | 
    
         
            +
                    version: 2.14.0
         
     | 
| 
      
 41 
     | 
    
         
            +
            description: Check your existing todo items, add new ones, update old one
         
     | 
| 
      
 42 
     | 
    
         
            +
            email:
         
     | 
| 
      
 43 
     | 
    
         
            +
            - buyer+donedone@his-service.net
         
     | 
| 
      
 44 
     | 
    
         
            +
            executables:
         
     | 
| 
      
 45 
     | 
    
         
            +
            - donedone
         
     | 
| 
      
 46 
     | 
    
         
            +
            extensions: []
         
     | 
| 
      
 47 
     | 
    
         
            +
            extra_rdoc_files: []
         
     | 
| 
      
 48 
     | 
    
         
            +
            files:
         
     | 
| 
      
 49 
     | 
    
         
            +
            - .gitignore
         
     | 
| 
      
 50 
     | 
    
         
            +
            - Gemfile
         
     | 
| 
      
 51 
     | 
    
         
            +
            - MIT-LICENSE
         
     | 
| 
      
 52 
     | 
    
         
            +
            - README.md
         
     | 
| 
      
 53 
     | 
    
         
            +
            - Rakefile
         
     | 
| 
      
 54 
     | 
    
         
            +
            - bin/donedone
         
     | 
| 
      
 55 
     | 
    
         
            +
            - donedone.gemspec
         
     | 
| 
      
 56 
     | 
    
         
            +
            - examples/lighthouse_csv_importer.rb
         
     | 
| 
      
 57 
     | 
    
         
            +
            - lib/donedone.rb
         
     | 
| 
      
 58 
     | 
    
         
            +
            - lib/donedone/constant.rb
         
     | 
| 
      
 59 
     | 
    
         
            +
            - lib/donedone/http.rb
         
     | 
| 
      
 60 
     | 
    
         
            +
            - lib/donedone/issue_tracker.rb
         
     | 
| 
      
 61 
     | 
    
         
            +
            - lib/donedone/multipart.rb
         
     | 
| 
      
 62 
     | 
    
         
            +
            - lib/donedone/version.rb
         
     | 
| 
      
 63 
     | 
    
         
            +
            - spec/donedone/constant_spec.rb
         
     | 
| 
      
 64 
     | 
    
         
            +
            - spec/donedone/http_spec.rb
         
     | 
| 
      
 65 
     | 
    
         
            +
            - spec/donedone/issue_tracker_spec.rb
         
     | 
| 
      
 66 
     | 
    
         
            +
            - spec/spec_helper.rb
         
     | 
| 
      
 67 
     | 
    
         
            +
            homepage: https://github.com/zoodles/DoneDone-API-Ruby
         
     | 
| 
      
 68 
     | 
    
         
            +
            licenses:
         
     | 
| 
      
 69 
     | 
    
         
            +
            - MIT
         
     | 
| 
      
 70 
     | 
    
         
            +
            metadata: {}
         
     | 
| 
      
 71 
     | 
    
         
            +
            post_install_message: 
         
     | 
| 
      
 72 
     | 
    
         
            +
            rdoc_options: []
         
     | 
| 
      
 73 
     | 
    
         
            +
            require_paths:
         
     | 
| 
      
 74 
     | 
    
         
            +
            - lib
         
     | 
| 
      
 75 
     | 
    
         
            +
            required_ruby_version: !ruby/object:Gem::Requirement
         
     | 
| 
      
 76 
     | 
    
         
            +
              requirements:
         
     | 
| 
      
 77 
     | 
    
         
            +
              - - '>='
         
     | 
| 
      
 78 
     | 
    
         
            +
                - !ruby/object:Gem::Version
         
     | 
| 
      
 79 
     | 
    
         
            +
                  version: '0'
         
     | 
| 
      
 80 
     | 
    
         
            +
            required_rubygems_version: !ruby/object:Gem::Requirement
         
     | 
| 
      
 81 
     | 
    
         
            +
              requirements:
         
     | 
| 
      
 82 
     | 
    
         
            +
              - - '>='
         
     | 
| 
      
 83 
     | 
    
         
            +
                - !ruby/object:Gem::Version
         
     | 
| 
      
 84 
     | 
    
         
            +
                  version: '0'
         
     | 
| 
      
 85 
     | 
    
         
            +
            requirements: []
         
     | 
| 
      
 86 
     | 
    
         
            +
            rubyforge_project: donedone
         
     | 
| 
      
 87 
     | 
    
         
            +
            rubygems_version: 2.0.6
         
     | 
| 
      
 88 
     | 
    
         
            +
            signing_key: 
         
     | 
| 
      
 89 
     | 
    
         
            +
            specification_version: 4
         
     | 
| 
      
 90 
     | 
    
         
            +
            summary: donedone.com api client
         
     | 
| 
      
 91 
     | 
    
         
            +
            test_files:
         
     | 
| 
      
 92 
     | 
    
         
            +
            - spec/donedone/constant_spec.rb
         
     | 
| 
      
 93 
     | 
    
         
            +
            - spec/donedone/http_spec.rb
         
     | 
| 
      
 94 
     | 
    
         
            +
            - spec/donedone/issue_tracker_spec.rb
         
     | 
| 
      
 95 
     | 
    
         
            +
            - spec/spec_helper.rb
         
     |