From b47a324d616b7fa4e23160abae357887b9dde13f Mon Sep 17 00:00:00 2001 From: Nihad Abbasov Date: Fri, 21 Sep 2012 22:57:46 +0500 Subject: [PATCH] initial implementation --- .gitignore | 17 +++ Gemfile | 4 + LICENSE.txt | 24 ++++ Rakefile | 9 ++ gitlab.gemspec | 25 ++++ lib/gitlab.rb | 29 ++++ lib/gitlab/api.rb | 17 +++ lib/gitlab/client.rb | 13 ++ lib/gitlab/client/issues.rb | 69 +++++++++ lib/gitlab/client/milestones.rb | 59 ++++++++ lib/gitlab/client/projects.rb | 155 +++++++++++++++++++++ lib/gitlab/client/repositories.rb | 67 +++++++++ lib/gitlab/client/snippets.rb | 64 +++++++++ lib/gitlab/client/users.rb | 89 ++++++++++++ lib/gitlab/configuration.rb | 42 ++++++ lib/gitlab/error.rb | 33 +++++ lib/gitlab/objectified_hash.rb | 18 +++ lib/gitlab/request.rb | 73 ++++++++++ lib/gitlab/version.rb | 3 + spec/fixtures/issue.json | 1 + spec/fixtures/issues.json | 1 + spec/fixtures/key.json | 1 + spec/fixtures/keys.json | 1 + spec/fixtures/milestone.json | 1 + spec/fixtures/milestones.json | 1 + spec/fixtures/project.json | 1 + spec/fixtures/project_branch.json | 1 + spec/fixtures/project_branches.json | 1 + spec/fixtures/project_commits.json | 1 + spec/fixtures/project_hook.json | 1 + spec/fixtures/project_hooks.json | 1 + spec/fixtures/project_issues.json | 1 + spec/fixtures/project_tags.json | 1 + spec/fixtures/projects.json | 1 + spec/fixtures/session.json | 1 + spec/fixtures/single_user.json | 1 + spec/fixtures/snippet.json | 1 + spec/fixtures/team_member.json | 1 + spec/fixtures/team_members.json | 1 + spec/fixtures/user.json | 1 + spec/fixtures/users.json | 1 + spec/gitlab/client/issues_spec.rb | 88 ++++++++++++ spec/gitlab/client/milestones_spec.rb | 66 +++++++++ spec/gitlab/client/projects_spec.rb | 177 ++++++++++++++++++++++++ spec/gitlab/client/repositories_spec.rb | 73 ++++++++++ spec/gitlab/client/snippets_spec.rb | 69 +++++++++ spec/gitlab/client/users_spec.rb | 129 +++++++++++++++++ spec/gitlab_spec.rb | 62 +++++++++ spec/spec_helper.rb | 64 +++++++++ 49 files changed, 1560 insertions(+) create mode 100644 .gitignore create mode 100644 Gemfile create mode 100644 LICENSE.txt create mode 100644 Rakefile create mode 100644 gitlab.gemspec create mode 100644 lib/gitlab.rb create mode 100644 lib/gitlab/api.rb create mode 100644 lib/gitlab/client.rb create mode 100644 lib/gitlab/client/issues.rb create mode 100644 lib/gitlab/client/milestones.rb create mode 100644 lib/gitlab/client/projects.rb create mode 100644 lib/gitlab/client/repositories.rb create mode 100644 lib/gitlab/client/snippets.rb create mode 100644 lib/gitlab/client/users.rb create mode 100644 lib/gitlab/configuration.rb create mode 100644 lib/gitlab/error.rb create mode 100644 lib/gitlab/objectified_hash.rb create mode 100644 lib/gitlab/request.rb create mode 100644 lib/gitlab/version.rb create mode 100644 spec/fixtures/issue.json create mode 100644 spec/fixtures/issues.json create mode 100644 spec/fixtures/key.json create mode 100644 spec/fixtures/keys.json create mode 100644 spec/fixtures/milestone.json create mode 100644 spec/fixtures/milestones.json create mode 100644 spec/fixtures/project.json create mode 100644 spec/fixtures/project_branch.json create mode 100644 spec/fixtures/project_branches.json create mode 100644 spec/fixtures/project_commits.json create mode 100644 spec/fixtures/project_hook.json create mode 100644 spec/fixtures/project_hooks.json create mode 100644 spec/fixtures/project_issues.json create mode 100644 spec/fixtures/project_tags.json create mode 100644 spec/fixtures/projects.json create mode 100644 spec/fixtures/session.json create mode 100644 spec/fixtures/single_user.json create mode 100644 spec/fixtures/snippet.json create mode 100644 spec/fixtures/team_member.json create mode 100644 spec/fixtures/team_members.json create mode 100644 spec/fixtures/user.json create mode 100644 spec/fixtures/users.json create mode 100644 spec/gitlab/client/issues_spec.rb create mode 100644 spec/gitlab/client/milestones_spec.rb create mode 100644 spec/gitlab/client/projects_spec.rb create mode 100644 spec/gitlab/client/repositories_spec.rb create mode 100644 spec/gitlab/client/snippets_spec.rb create mode 100644 spec/gitlab/client/users_spec.rb create mode 100644 spec/gitlab_spec.rb create mode 100644 spec/spec_helper.rb diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..d87d4be66 --- /dev/null +++ b/.gitignore @@ -0,0 +1,17 @@ +*.gem +*.rbc +.bundle +.config +.yardoc +Gemfile.lock +InstalledFiles +_yardoc +coverage +doc/ +lib/bundler/man +pkg +rdoc +spec/reports +test/tmp +test/version_tmp +tmp diff --git a/Gemfile b/Gemfile new file mode 100644 index 000000000..54fbdf177 --- /dev/null +++ b/Gemfile @@ -0,0 +1,4 @@ +source 'https://rubygems.org' + +# Specify your gem's dependencies in gitlab.gemspec +gemspec diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 000000000..aaf7c6fc3 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,24 @@ +Copyright (c) 2012 Nihad Abbasov / NARKOZ +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/Rakefile b/Rakefile new file mode 100644 index 000000000..bf451bdcb --- /dev/null +++ b/Rakefile @@ -0,0 +1,9 @@ +require "bundler/gem_tasks" + +require 'rspec/core/rake_task' +RSpec::Core::RakeTask.new(:spec) do |spec| + spec.pattern = FileList['spec/**/*_spec.rb'] + spec.rspec_opts = ['--color', '--format d'] +end + +task :default => :spec diff --git a/gitlab.gemspec b/gitlab.gemspec new file mode 100644 index 000000000..26fc89fd1 --- /dev/null +++ b/gitlab.gemspec @@ -0,0 +1,25 @@ +# -*- encoding: utf-8 -*- +lib = File.expand_path('../lib', __FILE__) +$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) +require 'gitlab/version' + +Gem::Specification.new do |gem| + gem.name = "gitlab" + gem.version = Gitlab::VERSION + gem.authors = ["Nihad Abbasov"] + gem.email = ["mail@narkoz.me"] + gem.description = %q{Ruby client for GitLab API} + gem.summary = %q{A Ruby wrapper for the GitLab API} + gem.homepage = "https://github.com/narkoz/gitlab" + + gem.files = `git ls-files`.split($/) + gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) } + gem.test_files = gem.files.grep(%r{^(test|spec|features)/}) + gem.require_paths = ["lib"] + + gem.add_runtime_dependency 'httparty' + + gem.add_development_dependency 'rake' + gem.add_development_dependency 'rspec' + gem.add_development_dependency 'webmock' +end diff --git a/lib/gitlab.rb b/lib/gitlab.rb new file mode 100644 index 000000000..afff42d95 --- /dev/null +++ b/lib/gitlab.rb @@ -0,0 +1,29 @@ +require File.expand_path('../gitlab/version', __FILE__) +require File.expand_path('../gitlab/objectified_hash', __FILE__) +require File.expand_path('../gitlab/configuration', __FILE__) +require File.expand_path('../gitlab/error', __FILE__) +require File.expand_path('../gitlab/request', __FILE__) +require File.expand_path('../gitlab/api', __FILE__) +require File.expand_path('../gitlab/client', __FILE__) + +module Gitlab + extend Configuration + + # Alias for Gitlab::Client.new + # + # @return [Gitlab::Client] + def self.client(options={}) + Gitlab::Client.new(options) + end + + # Delegate to Gitlab::Client + def self.method_missing(method, *args, &block) + return super unless client.respond_to?(method) + client.send(method, *args, &block) + end + + # Delegate to Gitlab::Client + def self.respond_to?(method) + return client.respond_to?(method) || super + end +end diff --git a/lib/gitlab/api.rb b/lib/gitlab/api.rb new file mode 100644 index 000000000..112b16c07 --- /dev/null +++ b/lib/gitlab/api.rb @@ -0,0 +1,17 @@ +module Gitlab + # @private + class API < Request + # @private + attr_accessor *Configuration::VALID_OPTIONS_KEYS + + # Creates a new API. + # @raise [Error:MissingCredentials] + def initialize(options={}) + options = Gitlab.options.merge(options) + Configuration::VALID_OPTIONS_KEYS.each do |key| + send("#{key}=", options[key]) + end + set_request_defaults @base_uri, @endpoint, @private_token + end + end +end diff --git a/lib/gitlab/client.rb b/lib/gitlab/client.rb new file mode 100644 index 000000000..7efed1165 --- /dev/null +++ b/lib/gitlab/client.rb @@ -0,0 +1,13 @@ +module Gitlab + # Wrapper for the Gitlab REST API. + class Client < API + Dir[File.expand_path('../client/*.rb', __FILE__)].each{|f| require f} + + include Gitlab::Client::Users + include Gitlab::Client::Issues + include Gitlab::Client::Milestones + include Gitlab::Client::Snippets + include Gitlab::Client::Projects + include Gitlab::Client::Repositories + end +end diff --git a/lib/gitlab/client/issues.rb b/lib/gitlab/client/issues.rb new file mode 100644 index 000000000..f4f05f9c4 --- /dev/null +++ b/lib/gitlab/client/issues.rb @@ -0,0 +1,69 @@ +class Gitlab::Client + # Defines methods related to issues. + module Issues + # Gets a list of user's issues. + # Will return a list of project's issues if project ID or code name passed. + # + # @example + # Gitlab.issues + # Gitlab.issues(5) + # Gitlab.issues('gitlab', :per_page => 40) + # + # @param [Integer, String] project The ID or code name of a project. + # @param [Hash] options A customizable set of options. + # @option options [Integer] :page The page number. + # @option options [Integer] :per_page The number of results per page. + # @return [Array] + def issues(project=nil, options={}) + if project.to_i.zero? + get("/issues", :query => options) + else + get("/projects/#{project}/issues", :query => options) + end + end + + # Gets a single issue. + # + # @example + # Gitlab.issue(5, 36) + # Gitlab.issue('gitlab', 42) + # + # @param [Integer, String] project The ID or code name of a project. + # @param [Integer] id The ID of an issue. + # @return [Array] + def issue(project, id) + get("/projects/#{project}/issues/#{id}") + end + + # Creates a new issue. + # + # @param [Integer, String] project The ID or code name of a project. + # @param [String] title The title of an issue. + # @param [Hash] options A customizable set of options. + # @option options [String] :description The description of an issue. + # @option options [Integer] :assignee_id The ID of a user to assign issue. + # @option options [Integer] :milestone_id The ID of a milestone to assign issue. + # @option options [String] :labels Comma-separated label names for an issue. + # @return [Gitlab::ObjectifiedHash] Information about created issue. + def create_issue(project, title, options={}) + body = {:title => title}.merge(options) + post("/projects/#{project}/issues", :body => body) + end + + # Updates an issue. + # + # @param [Integer, String] project The ID or code name of a project. + # @param [Integer] id The ID of an issue. + # @param [Hash] options A customizable set of options. + # @option options [String] :title The title of an issue. + # @option options [String] :description The description of an issue. + # @option options [Integer] :assignee_id The ID of a user to assign issue. + # @option options [Integer] :milestone_id The ID of a milestone to assign issue. + # @option options [String] :labels Comma-separated label names for an issue. + # @option options [Boolean] :closed The state of an issue (0 = false, 1 = true). + # @return [Gitlab::ObjectifiedHash] Information about updated issue. + def edit_issue(project, id, options={}) + put("/projects/#{project}/issues/#{id}", :body => options) + end + end +end diff --git a/lib/gitlab/client/milestones.rb b/lib/gitlab/client/milestones.rb new file mode 100644 index 000000000..502281e14 --- /dev/null +++ b/lib/gitlab/client/milestones.rb @@ -0,0 +1,59 @@ +class Gitlab::Client + # Defines methods related to milestones. + module Milestones + # Gets a list of project's milestones. + # + # @example + # Gitlab.milestones(5) + # Gitlab.milestones('gitlab') + # + # @param [Integer, String] project The ID or code name of a project. + # @param [Hash] options A customizable set of options. + # @option options [Integer] :page The page number. + # @option options [Integer] :per_page The number of results per page. + # @return [Array] + def milestones(project, options={}) + get("/projects/#{project}/milestones", :query => options) + end + + # Gets a single milestone. + # + # @example + # Gitlab.milestone(5, 36) + # Gitlab.milestone('gitlab', 42) + # + # @param [Integer, String] project The ID or code name of a project. + # @param [Integer] id The ID of a milestone. + # @return [Array] + def milestone(project, id) + get("/projects/#{project}/milestones/#{id}") + end + + # Creates a new milestone. + # + # @param [Integer, String] project The ID or code name of a project. + # @param [String] title The title of a milestone. + # @param [Hash] options A customizable set of options. + # @option options [String] :description The description of a milestone. + # @option options [String] :due_date The due date of a milestone. + # @return [Gitlab::ObjectifiedHash] Information about created milestone. + def create_milestone(project, title, options={}) + body = {:title => title}.merge(options) + post("/projects/#{project}/milestones", :body => body) + end + + # Updates a milestone. + # + # @param [Integer, String] project The ID or code name of a project. + # @param [Integer] id The ID of a milestone. + # @param [Hash] options A customizable set of options. + # @option options [String] :title The title of a milestone. + # @option options [String] :description The description of a milestone. + # @option options [String] :due_date The due date of a milestone. + # @option options [Boolean] :closed The state of a milestone (0 = false, 1 = true). + # @return [Gitlab::ObjectifiedHash] Information about updated milestone. + def edit_milestone(project, id, options={}) + put("/projects/#{project}/milestones/#{id}", :body => options) + end + end +end diff --git a/lib/gitlab/client/projects.rb b/lib/gitlab/client/projects.rb new file mode 100644 index 000000000..93b0350c9 --- /dev/null +++ b/lib/gitlab/client/projects.rb @@ -0,0 +1,155 @@ +class Gitlab::Client + # Defines methods related to projects. + module Projects + # Gets a list of projects owned by the authenticated user. + # + # @example + # Gitlab.projects + # + # @param [Hash] options A customizable set of options. + # @option options [Integer] :page The page number. + # @option options [Integer] :per_page The number of results per page. + # @return [Array] + def projects(options={}) + get("/projects", :query => options) + end + + # Gets information about a project. + # + # @example + # Gitlab.project(3) + # Gitlab.project('gitlab') + # + # @param [Integer, String] id The ID or code name of a project. + # @return [Gitlab::ObjectifiedHash] + def project(id) + get("/projects/#{id}") + end + + # Creates a new project. + # + # @example + # Gitlab.create_project('gitlab') + # Gitlab.create_project('viking', :description => 'Awesome project') + # Gitlab.create_project('Red', :wall_enabled => false) + # + # @param [String] name The name of a project. + # @param [Hash] options A customizable set of options. + # @option options [String] :code The code name of a project. + # @option options [String] :path The path of a project. + # @option options [String] :description The description of a project. + # @option options [String] :default_branch The default branch of a project. + # @option options [Boolean] :wiki_enabled The wiki integration for a project (0 = false, 1 = true). + # @option options [Boolean] :wall_enabled The wall functionality for a project (0 = false, 1 = true). + # @option options [Boolean] :issues_enabled The issues integration for a project (0 = false, 1 = true). + # @option options [Boolean] :merge_requests_enabled The merge requests functionality for a project (0 = false, 1 = true). + # @return [Gitlab::ObjectifiedHash] Information about created project. + def create_project(name, options={}) + post("/projects", :body => {:name => name}.merge(options)) + end + + # Gets a list of project team members. + # + # @example + # Gitlab.team_members(42) + # Gitlab.team_members('gitlab') + # + # @param [Integer, String] project The ID or code name of a project. + # @param [Hash] options A customizable set of options. + # @option options [Integer] :page The page number. + # @option options [Integer] :per_page The number of results per page. + # @return [Array] + def team_members(project, options={}) + get("/projects/#{project}/members", :query => options) + end + + # Gets a project team member. + # + # @example + # Gitlab.team_member('gitlab', 2) + # + # @param [Integer, String] project The ID or code name of a project. + # @param [Integer] id The ID of a project team member. + # @return [Array] + def team_member(project, id) + get("/projects/#{project}/members/#{id}") + end + + # Adds a user to project team. + # + # @example + # Gitlab.add_team_member('gitlab', 2, 40) + # + # @param [Integer, String] project The ID or code name of a project. + # @param [Integer] id The ID of a user. + # @param [Integer] access_level The access level to project. + # @return [Array] Information about added team member. + def add_team_member(project, id, access_level) + post("/projects/#{project}/members/#{id}", :body => {:access_level => access_level}) + end + + # Updates a team member's project access level. + # + # @example + # Gitlab.team_members('gitlab', 3, 20) + # + # @param [Integer, String] project The ID or code name of a project. + # @param [Integer] id The ID of a user. + # @param [Integer] access_level The access level to project. + # @return [Array] Information about updated team member. + def edit_team_member(project, id, access_level) + put("/projects/#{project}/members/#{id}", :body => {:access_level => access_level}) + end + + # Removes a user from project team. + # + # @example + # Gitlab.remove_team_member('gitlab', 2) + # + # @param [Integer, String] project The ID or code name of a project. + # @param [Integer] id The ID of a user. + # @return [Array] Information about removed team member. + def remove_team_member(project, id) + delete("/projects/#{project}/members/#{id}") + end + + # Gets a list of project hooks. + # + # @example + # Gitlab.project_hooks(42) + # Gitlab.project_hooks('gitlab') + # + # @param [Integer, String] project The ID or code name of a project. + # @param [Hash] options A customizable set of options. + # @option options [Integer] :page The page number. + # @option options [Integer] :per_page The number of results per page. + # @return [Array] + def project_hooks(project, options={}) + get("/projects/#{project}/hooks", :query => options) + end + + # Adds a new hook to the project. + # + # @example + # Gitlab.project_hooks(42, 'https://api.example.net/v1/webhooks/ci') + # + # @param [Integer, String] project The ID or code name of a project. + # @param [String] url The hook URL. + # @return [Gitlab::ObjectifiedHash] Information about added hook. + def add_project_hook(project, url) + post("/projects/#{project}/hooks", :body => {:url => url}) + end + + # Deletes a hook from project. + # + # @example + # Gitlab.delete_project_hook('gitlab', 4) + # + # @param [Integer, String] project The ID or code name of a project. + # @param [String] id The ID of the hook. + # @return [Gitlab::ObjectifiedHash] Information about deleted hook. + def delete_project_hook(project, id) + delete("/projects/#{project}/hooks/#{id}") + end + end +end diff --git a/lib/gitlab/client/repositories.rb b/lib/gitlab/client/repositories.rb new file mode 100644 index 000000000..f426c9ced --- /dev/null +++ b/lib/gitlab/client/repositories.rb @@ -0,0 +1,67 @@ +class Gitlab::Client + # Defines methods related to repositories. + module Repositories + # Gets a list of project repository tags. + # + # @example + # Gitlab.tags(42) + # Gitlab.repo_tags('gitlab') + # + # @param [Integer, String] project The ID or code name of a project. + # @param [Hash] options A customizable set of options. + # @option options [Integer] :page The page number. + # @option options [Integer] :per_page The number of results per page. + # @return [Array] + def tags(project, options={}) + get("/projects/#{project}/repository/tags", :query => options) + end + alias :repo_tags :tags + + # Gets a list of project repositiory branches. + # + # @example + # Gitlab.branches(42) + # Gitlab.repo_branches('gitlab') + # + # @param [Integer, String] project The ID or code name of a project. + # @param [Hash] options A customizable set of options. + # @option options [Integer] :page The page number. + # @option options [Integer] :per_page The number of results per page. + # @return [Array] + def branches(project, options={}) + get("/projects/#{project}/repository/branches", :query => options) + end + alias :repo_branches :branches + + # Gets information about a repository branch. + # + # @example + # Gitlab.branch(3, 'api') + # Gitlab.repo_branch(5, 'master') + # + # @param [Integer, String] project The ID or code name of a project. + # @param [String] branch The name of the branch. + # @return [Gitlab::ObjectifiedHash] + def branch(project, branch) + get("/projects/#{project}/repository/branches/#{branch}") + end + alias :repo_branch :branch + + # Gets a list of project commits. + # + # @example + # Gitlab.commits('viking') + # Gitlab.repo_commits('gitlab', :ref_name => 'api') + # + # @param [String] project The name of a project. + # @param [Hash] options A customizable set of options. + # @option options [String] :ref_name The branch or tag name of a project repository. + # @option options [Integer] :page The page number. + # @option options [Integer] :per_page The number of results per page. + # @return [Array] + def commits(project, options={}) + get("/projects/#{project}/repository/commits", :query => options) + end + alias :repo_commits :commits + end +end diff --git a/lib/gitlab/client/snippets.rb b/lib/gitlab/client/snippets.rb new file mode 100644 index 000000000..e11127926 --- /dev/null +++ b/lib/gitlab/client/snippets.rb @@ -0,0 +1,64 @@ +class Gitlab::Client + # Defines methods related to snippets. + module Snippets + # Gets information about a snippet. + # + # @example + # Gitlab.snippet(2, 14) + # Gitlab.snippet('gitlab', 34) + # + # @param [Integer, String] project The ID or code name of a project. + # @param [Integer] id The ID of a snippet. + # @return [Gitlab::ObjectifiedHash] + def snippet(project, id) + get("/projects/#{project}/snippets/#{id}") + end + + # Creates a new snippet. + # + # @example + # Gitlab.create_snippet('gitlab', + # {:title => 'REST', :file_name => 'api.rb', :code => 'some code'}) + # + # @param [Integer, String] project The ID or code name of a project. + # @param [Hash] options A customizable set of options. + # @option options [String] :title The title of a snippet. + # @option options [String] :file_name The name of a snippet file. + # @option options [String] :code The content of a snippet. + # @option options [String] :lifetime The expiration date of a snippet. + # @return [Gitlab::ObjectifiedHash] Information about created snippet. + def create_snippet(project, options={}) + post("/projects/#{project}/snippets", :body => options) + end + + # Updates a snippet. + # + # @example + # Gitlab.edit_snippet('gitlab', 34, :file_name => 'README.txt') + # + # @param [Integer, String] project The ID or code name of a project. + # @param [Integer] id The ID of a snippet. + # @param [Hash] options A customizable set of options. + # @option options [String] :title The title of a snippet. + # @option options [String] :file_name The name of a snippet file. + # @option options [String] :code The content of a snippet. + # @option options [String] :lifetime The expiration date of a snippet. + # @return [Gitlab::ObjectifiedHash] Information about updated snippet. + def edit_snippet(project, id, options={}) + put("/projects/#{project}/snippets/#{id}", :body => options) + end + + # Deletes a snippet. + # + # @example + # Gitlab.delete_snippet(2, 14) + # Gitlab.delete_snippet('gitlab', 34) + # + # @param [Integer, String] project The ID or code name of a project. + # @param [Integer] id The ID of a snippet. + # @return [Gitlab::ObjectifiedHash] Information about deleted snippet. + def delete_snippet(project, id) + delete("/projects/#{project}/snippets/#{id}") + end + end +end diff --git a/lib/gitlab/client/users.rb b/lib/gitlab/client/users.rb new file mode 100644 index 000000000..239db0b23 --- /dev/null +++ b/lib/gitlab/client/users.rb @@ -0,0 +1,89 @@ +class Gitlab::Client + # Defines methods related to users. + module Users + # Gets a list of users. + # + # @example + # Gitlab.users + # + # @param [Hash] options A customizable set of options. + # @option options [Integer] :page The page number. + # @option options [Integer] :per_page The number of results per page. + # @return [Array] + def users(options={}) + get("/users", :query => options) + end + + # Gets information about a user. + # Will return information about an authorized user if no ID passed. + # + # @example + # Gitlab.user + # Gitlab.user(2) + # + # @param [Integer] id The ID of a user. + # @return [Gitlab::ObjectifiedHash] + def user(id=nil) + id.to_i.zero? ? get("/user") : get("/users/#{id}") + end + + # Creates a new user session. + # + # @example + # Gitlab.session('jack@example.com', 'secret12345') + # + # @param [String] email The email of a user. + # @param [String] password The password of a user. + # @return [Gitlab::ObjectifiedHash] + def session(email, password) + post("/session", :body => {:email => email, :password => password}) + end + + # Gets a list of user's SSH keys. + # + # @example + # Gitlab.ssh_keys + # + # @param [Hash] options A customizable set of options. + # @option options [Integer] :page The page number. + # @option options [Integer] :per_page The number of results per page. + # @return [Array] + def ssh_keys(options={}) + get("/user/keys", :query => options) + end + + # Gets information about SSH key. + # + # @example + # Gitlab.ssh_key(1) + # + # @param [Integer] id The ID of a user's SSH key. + # @return [Gitlab::ObjectifiedHash] + def ssh_key(id) + get("/user/keys/#{id}") + end + + # Creates a new SSH key. + # + # @example + # Gitlab.create_ssh_key('key title', 'key body') + # + # @param [String] title The title of an SSH key. + # @param [String] key The SSH key body. + # @return [Gitlab::ObjectifiedHash] Information about created SSH key. + def create_ssh_key(title, key) + post("/user/keys", :body => {:title => title, :key => key}) + end + + # Deletes an SSH key. + # + # @example + # Gitlab.delete_ssh_key(1) + # + # @param [Integer] id The ID of a user's SSH key. + # @return [Gitlab::ObjectifiedHash] Information about deleted SSH key. + def delete_ssh_key(id) + delete("/user/keys/#{id}") + end + end +end diff --git a/lib/gitlab/configuration.rb b/lib/gitlab/configuration.rb new file mode 100644 index 000000000..40ddec1ed --- /dev/null +++ b/lib/gitlab/configuration.rb @@ -0,0 +1,42 @@ +module Gitlab + # Defines constants and methods related to configuration. + module Configuration + # An array of valid keys in the options hash when configuring a Gitlab::API. + VALID_OPTIONS_KEYS = [:base_uri, :endpoint, :private_token, :user_agent].freeze + + # The API endpoint that will be used if none is set. + DEFAULT_ENDPOINT = "api/v2".freeze + + # The user agent that will be sent to the API endpoint if none is set. + DEFAULT_USER_AGENT = "Gitlab Ruby Gem #{Gitlab::VERSION}".freeze + + # @private + attr_accessor *VALID_OPTIONS_KEYS + + # Sets all configuration options to their default values + # when this module is extended. + def self.extended(base) + base.reset + end + + # Convenience method to allow configuration options to be set in a block. + def configure + yield self + end + + # Creates a hash of options and their values. + def options + VALID_OPTIONS_KEYS.inject({}) do |option, key| + option.merge!(key => send(key)) + end + end + + # Resets all configuration options to the defaults. + def reset + self.base_uri = nil + self.endpoint = DEFAULT_ENDPOINT + self.private_token = nil + self.user_agent = DEFAULT_USER_AGENT + end + end +end diff --git a/lib/gitlab/error.rb b/lib/gitlab/error.rb new file mode 100644 index 000000000..a13431bb6 --- /dev/null +++ b/lib/gitlab/error.rb @@ -0,0 +1,33 @@ +module Gitlab + module Error + # Custom error class for rescuing from all Gitlab errors. + class Error < StandardError; end + + # Raised when API endpoint credentials not configured. + class MissingCredentials < Error; end + + # Raised when impossible to parse response body. + class Parsing < Error; end + + # Raised when API endpoint returns the HTTP status code 400. + class BadRequest < Error; end + + # Raised when API endpoint returns the HTTP status code 401. + class Unauthorized < Error; end + + # Raised when API endpoint returns the HTTP status code 403. + class Forbidden < Error; end + + # Raised when API endpoint returns the HTTP status code 404. + class NotFound < Error; end + + # Raised when API endpoint returns the HTTP status code 500. + class InternalServerError < Error; end + + # Raised when API endpoint returns the HTTP status code 502. + class BadGateway < Error; end + + # Raised when API endpoint returns the HTTP status code 503. + class ServiceUnavailable < Error; end + end +end diff --git a/lib/gitlab/objectified_hash.rb b/lib/gitlab/objectified_hash.rb new file mode 100644 index 000000000..370665e83 --- /dev/null +++ b/lib/gitlab/objectified_hash.rb @@ -0,0 +1,18 @@ +module Gitlab + # Converts hashes to the objects. + class ObjectifiedHash + # Creates a new ObjectifiedHash. + def initialize(hash) + @data = hash.inject({}) do |data, (key,value)| + value = ObjectifiedHash.new(value) if value.is_a? Hash + data[key.to_s] = value + data + end + end + + # Delegate to ObjectifiedHash + def method_missing(key) + @data.key?(key.to_s) ? @data[key.to_s] : nil + end + end +end diff --git a/lib/gitlab/request.rb b/lib/gitlab/request.rb new file mode 100644 index 000000000..79873bde9 --- /dev/null +++ b/lib/gitlab/request.rb @@ -0,0 +1,73 @@ +require 'httparty' + +module Gitlab + # @private + class Request + include HTTParty + format :json + headers 'Accept' => 'application/json' + parser Proc.new {|body| make_objectified_hash(body)} + + # Parses the response body. + def self.make_objectified_hash(body) + begin + response = MultiJson.respond_to?(:adapter) ? MultiJson.load(body) : MultiJson.decode(body) + rescue MultiJson::DecodeError + raise Error::Parsing.new "Couldn't parse a response body" + end + + if response.is_a? Hash + ObjectifiedHash.new response + elsif response.is_a? Array + response.collect! {|e| ObjectifiedHash.new(e)} + else + raise Error::Parsing.new "Couldn't parse a response body" + end + end + + def get(path, options={}) + validate_response self.class.get(path, options) + end + + def post(path, options={}) + validate_response self.class.post(path, options) + end + + def put(path, options={}) + validate_response self.class.put(path, options) + end + + def delete(path) + validate_response self.class.delete(path) + end + + def set_request_defaults(base_uri, endpoint, private_token) + raise Error::MissingCredentials.new("Please set a base_uri for API endpoint") unless base_uri + raise Error::MissingCredentials.new("Please set a private_token for API endpoint") unless private_token + + self.class.base_uri "#{base_uri}/#{endpoint}" + self.class.default_params :private_token => private_token + end + + def validate_response(response) + case response.code + when 400 + raise Error::BadRequest.new "Server responsed with code #{response.code}" + when 401 + raise Error::Unauthorized.new "Server responsed with code #{response.code}" + when 403 + raise Error::Forbidden.new "Server responsed with code #{response.code}" + when 404 + raise Error::NotFound.new "Server responsed with code #{response.code}" + when 500 + raise Error::InternalServerError.new "Server responsed with code #{response.code}" + when 502 + raise Error::BadGateway.new "Server responsed with code #{response.code}" + when 503 + raise Error::ServiceUnavailable.new "Server responsed with code #{response.code}" + end + + response.parsed_response + end + end +end diff --git a/lib/gitlab/version.rb b/lib/gitlab/version.rb new file mode 100644 index 000000000..bd809e171 --- /dev/null +++ b/lib/gitlab/version.rb @@ -0,0 +1,3 @@ +module Gitlab + VERSION = "0.0.1" +end diff --git a/spec/fixtures/issue.json b/spec/fixtures/issue.json new file mode 100644 index 000000000..9f70318a7 --- /dev/null +++ b/spec/fixtures/issue.json @@ -0,0 +1 @@ +{"id":33,"project_id":3,"title":"Beatae possimus nostrum nihil reiciendis laboriosam nihil delectus alias accusantium dolor unde.","description":null,"labels":[],"milestone":null,"assignee":{"id":2,"email":"jack@example.com","name":"Jack Smith","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"author":{"id":2,"email":"jack@example.com","name":"Jack Smith","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"closed":false,"updated_at":"2012-09-17T09:42:20Z","created_at":"2012-09-17T09:42:20Z"} \ No newline at end of file diff --git a/spec/fixtures/issues.json b/spec/fixtures/issues.json new file mode 100644 index 000000000..62e4cadd2 --- /dev/null +++ b/spec/fixtures/issues.json @@ -0,0 +1 @@ +[{"id":1,"project_id":1,"title":"Culpa eius recusandae suscipit autem distinctio dolorum.","description":null,"labels":[],"milestone":null,"assignee":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"author":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"closed":false,"updated_at":"2012-09-17T09:42:20Z","created_at":"2012-09-17T09:42:20Z"},{"id":6,"project_id":2,"title":"Ut in dolorum omnis sed sit aliquam.","description":null,"labels":[],"milestone":null,"assignee":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"author":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"closed":false,"updated_at":"2012-09-17T09:42:20Z","created_at":"2012-09-17T09:42:20Z"},{"id":12,"project_id":3,"title":"Veniam et tempore quidem eum reprehenderit cupiditate non aut velit eaque.","description":null,"labels":[],"milestone":null,"assignee":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"author":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"closed":false,"updated_at":"2012-09-17T09:42:20Z","created_at":"2012-09-17T09:42:20Z"},{"id":21,"project_id":1,"title":"Vitae ea aliquam et quo eligendi sapiente voluptatum labore hic nihil culpa.","description":null,"labels":[],"milestone":null,"assignee":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"author":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"closed":false,"updated_at":"2012-09-17T09:42:20Z","created_at":"2012-09-17T09:42:20Z"},{"id":26,"project_id":2,"title":"Quo enim est nihil atque placeat voluptas neque eos voluptas.","description":null,"labels":[],"milestone":null,"assignee":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"author":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"closed":false,"updated_at":"2012-09-17T09:42:20Z","created_at":"2012-09-17T09:42:20Z"},{"id":32,"project_id":3,"title":"Deserunt tenetur impedit est beatae voluptas voluptas quaerat quisquam.","description":null,"labels":[],"milestone":null,"assignee":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"author":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"closed":false,"updated_at":"2012-09-17T09:42:20Z","created_at":"2012-09-17T09:42:20Z"}] \ No newline at end of file diff --git a/spec/fixtures/key.json b/spec/fixtures/key.json new file mode 100644 index 000000000..6595c8ceb --- /dev/null +++ b/spec/fixtures/key.json @@ -0,0 +1 @@ +{"id":1,"title":"narkoz@helium","key":"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCkUsh42Nh1yefGd1jbSELn5XsY8p5Oxmau0/1HqHnjuYOaj5X+kHccFDwtmtg9Ox8ua/+WptNsiE8IUwsD3zKgEjajgwq3gMeeFdxfXwM+tEvHOOMV9meRrgRWGYCToPbT6sR7/YMAYa7cPqWSpx/oZhYfz4XtoMv3ZZT1fZMmx3MY3HwXwW8j+obJyN2K4LN0TFi9RPgWWYn0DCyb9OccmABimt3i74WoJ/OT8r6/7swce8+OSe0Q2wBhyTtvxg2vtUcoek8Af+EZaUMBwSEzEsocOCzwQvjF5XUk5o7dJ8nP8W3RE60JWX57t16eQm7lBmumLYfszpn2isd6W7a1 narkoz@helium"} diff --git a/spec/fixtures/keys.json b/spec/fixtures/keys.json new file mode 100644 index 000000000..d81fca6ad --- /dev/null +++ b/spec/fixtures/keys.json @@ -0,0 +1 @@ +[{"id":1,"title":"narkoz@helium","key":"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCkUsh42Nh1yefGd1jbSELn5XsY8p5Oxmau0/1HqHnjuYOaj5X+kHccFDwtmtg9Ox8ua/+WptNsiE8IUwsD3zKgEjajgwq3gMeeFdxfXwM+tEvHOOMV9meRrgRWGYCToPbT6sR7/YMAYa7cPqWSpx/oZhYfz4XtoMv3ZZT1fZMmx3MY3HwXwW8j+obJyN2K4LN0TFi9RPgWWYn0DCyb9OccmABimt3i74WoJ/OT8r6/7swce8+OSe0Q2wBhyTtvxg2vtUcoek8Af+EZaUMBwSEzEsocOCzwQvjF5XUk5o7dJ8nP8W3RE60JWX57t16eQm7lBmumLYfszpn2isd6W7a1 narkoz@helium"}] diff --git a/spec/fixtures/milestone.json b/spec/fixtures/milestone.json new file mode 100644 index 000000000..94ea3d360 --- /dev/null +++ b/spec/fixtures/milestone.json @@ -0,0 +1 @@ +{"id":1,"project_id":3,"title":"3.0","description":"","due_date":"2012-10-22","closed":false,"updated_at":"2012-09-17T10:15:31Z","created_at":"2012-09-17T10:15:31Z"} \ No newline at end of file diff --git a/spec/fixtures/milestones.json b/spec/fixtures/milestones.json new file mode 100644 index 000000000..f9e309af6 --- /dev/null +++ b/spec/fixtures/milestones.json @@ -0,0 +1 @@ +[{"id":1,"project_id":3,"title":"3.0","description":"","due_date":"2012-10-22","closed":false,"updated_at":"2012-09-17T10:15:31Z","created_at":"2012-09-17T10:15:31Z"}] \ No newline at end of file diff --git a/spec/fixtures/project.json b/spec/fixtures/project.json new file mode 100644 index 000000000..b61b8bb2a --- /dev/null +++ b/spec/fixtures/project.json @@ -0,0 +1 @@ +{"id":3,"code":"gitlab","name":"Gitlab","description":null,"path":"gitlab","default_branch":null,"owner":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"private":true,"issues_enabled":true,"merge_requests_enabled":true,"wall_enabled":true,"wiki_enabled":true,"created_at":"2012-09-17T09:41:58Z"} \ No newline at end of file diff --git a/spec/fixtures/project_branch.json b/spec/fixtures/project_branch.json new file mode 100644 index 000000000..95a000651 --- /dev/null +++ b/spec/fixtures/project_branch.json @@ -0,0 +1 @@ +{"name":"api","commit":{"id":"f7dd067490fe57505f7226c3b54d3127d2f7fd46","parents":[{"id":"949b1df930bedace1dbd755aaa4a82e8c451a616"}],"tree":"f8c4b21c036339f92fcc5482aa28a41250553b27","message":"API: expose issues project id","author":{"name":"Nihad Abbasov","email":"narkoz.2008@gmail.com"},"committer":{"name":"Nihad Abbasov","email":"narkoz.2008@gmail.com"},"authored_date":"2012-07-25T04:22:21-07:00","committed_date":"2012-07-25T04:22:21-07:00"}} \ No newline at end of file diff --git a/spec/fixtures/project_branches.json b/spec/fixtures/project_branches.json new file mode 100644 index 000000000..05a39447d --- /dev/null +++ b/spec/fixtures/project_branches.json @@ -0,0 +1 @@ +[{"name":"api","commit":{"id":"f7dd067490fe57505f7226c3b54d3127d2f7fd46","parents":[{"id":"949b1df930bedace1dbd755aaa4a82e8c451a616"}],"tree":"f8c4b21c036339f92fcc5482aa28a41250553b27","message":"API: expose issues project id","author":{"name":"Nihad Abbasov","email":"narkoz.2008@gmail.com"},"committer":{"name":"Nihad Abbasov","email":"narkoz.2008@gmail.com"},"authored_date":"2012-07-25T04:22:21-07:00","committed_date":"2012-07-25T04:22:21-07:00"}},{"name":"dashboard-feed","commit":{"id":"f8f6ff065eccc6ede4d35ed87a09bb962b84ca25","parents":[{"id":"2cf8010792c3075824ee27d0f037aeb178cbbf7e"}],"tree":"e17f2157143d550891d4669c10b7446e4739bc6d","message":"add projects atom feed","author":{"name":"Nihad Abbasov","email":"narkoz.2008@gmail.com"},"committer":{"name":"Nihad Abbasov","email":"narkoz.2008@gmail.com"},"authored_date":"2012-05-31T23:42:02-07:00","committed_date":"2012-05-31T23:42:02-07:00"}},{"name":"master","commit":{"id":"2cf8010792c3075824ee27d0f037aeb178cbbf7e","parents":[{"id":"af226ae9c9af406c8a0e0bbdf364563495c2f432"},{"id":"e851cb07762aa464aae10e8b4b28de87c1a6f925"}],"tree":"6c6845838039f01723d91f395a1d2fa1dcc82522","message":"Merge pull request #868 from SaitoWu/bugfix/encoding\n\nBugfix/encoding","author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"authored_date":"2012-05-30T00:24:43-07:00","committed_date":"2012-05-30T00:24:43-07:00"}},{"name":"preview_notes","commit":{"id":"3749e0d99ac6bfbc65889b1b7a5310e14e7fe89a","parents":[{"id":"2483181f2c3d4ea7d2c68147b19bc07fc3937b0c"}],"tree":"f8c56161b0d6561568f088df9961362eb1ece88b","message":"pass project_id to notes preview path","author":{"name":"Nihad Abbasov","email":"narkoz.2008@gmail.com"},"committer":{"name":"Nihad Abbasov","email":"narkoz.2008@gmail.com"},"authored_date":"2012-08-09T23:46:27-07:00","committed_date":"2012-08-09T23:46:27-07:00"}},{"name":"refactoring","commit":{"id":"7c7761099cae83f59fe5780340e100be890847b2","parents":[{"id":"058d80b3363dd4fc4417ca4f60f76119188a2470"}],"tree":"d7d4a94c700dc0e84ee943019213d2358a49c413","message":"fix deprecation warnings","author":{"name":"Nihad Abbasov","email":"narkoz.2008@gmail.com"},"committer":{"name":"Nihad Abbasov","email":"narkoz.2008@gmail.com"},"authored_date":"2012-05-29T07:16:28-07:00","committed_date":"2012-05-29T07:16:28-07:00"}}] diff --git a/spec/fixtures/project_commits.json b/spec/fixtures/project_commits.json new file mode 100644 index 000000000..58cb5020d --- /dev/null +++ b/spec/fixtures/project_commits.json @@ -0,0 +1 @@ +[{"id":"f7dd067490fe57505f7226c3b54d3127d2f7fd46","short_id":"f7dd067490f","title":"API: expose issues project id","author_name":"Nihad Abbasov","author_email":"narkoz.2008@gmail.com","created_at":"2012-07-25T04:22:21-07:00"},{"id":"949b1df930bedace1dbd755aaa4a82e8c451a616","short_id":"949b1df930b","title":"API: update docs","author_name":"Nihad Abbasov","author_email":"narkoz.2008@gmail.com","created_at":"2012-07-25T02:35:41-07:00"},{"id":"1b95c8bff351f6718ec31ac1de1e48c57bc95d44","short_id":"1b95c8bff35","title":"API: ability to get project by id","author_name":"Nihad Abbasov","author_email":"narkoz.2008@gmail.com","created_at":"2012-07-25T02:18:30-07:00"},{"id":"92d98f5a0c28bffd7b070cda190b07ab72667d58","short_id":"92d98f5a0c2","title":"Merge pull request #1118 from patthoyts/pt/ldap-missing-password","author_name":"Dmitriy Zaporozhets","author_email":"dmitriy.zaporozhets@gmail.com","created_at":"2012-07-25T01:51:06-07:00"},{"id":"60d3e94874964a626f105d3598e1c122addcf43e","short_id":"60d3e948749","title":"Merge pull request #1122 from patthoyts/pt/missing-log","author_name":"Dmitriy Zaporozhets","author_email":"dmitriy.zaporozhets@gmail.com","created_at":"2012-07-25T01:50:34-07:00"},{"id":"b683a71aa1230f17f9df47661c77dfeae27027de","short_id":"b683a71aa12","title":"Merge pull request #1135 from NARKOZ/api","author_name":"Dmitriy Zaporozhets","author_email":"dmitriy.zaporozhets@gmail.com","created_at":"2012-07-25T01:48:00-07:00"},{"id":"fbb41100db35cf2def2c8b4d896b7015d56bd15b","short_id":"fbb41100db3","title":"update help section with issues API docs","author_name":"Nihad Abbasov","author_email":"narkoz.2008@gmail.com","created_at":"2012-07-24T05:52:43-07:00"},{"id":"eca823c1c7cef45cc18c6ab36d2327650c85bfc3","short_id":"eca823c1c7c","title":"Merge branch 'master' into api","author_name":"Nihad Abbasov","author_email":"narkoz.2008@gmail.com","created_at":"2012-07-24T05:46:36-07:00"},{"id":"024e0348904179a8dea81c01e27a5f014cf57499","short_id":"024e0348904","title":"update API docs","author_name":"Nihad Abbasov","author_email":"narkoz.2008@gmail.com","created_at":"2012-07-24T05:25:01-07:00"},{"id":"7b33d8cbcab3b0ee5789ec607455ab62130db69f","short_id":"7b33d8cbcab","title":"add issues API","author_name":"Nihad Abbasov","author_email":"narkoz.2008@gmail.com","created_at":"2012-07-24T05:19:51-07:00"},{"id":"6035ad7e1fe519d0c6a42731790183889e3ba31d","short_id":"6035ad7e1fe","title":"Create the githost.log file if necessary.","author_name":"Pat Thoyts","author_email":"patthoyts@users.sourceforge.net","created_at":"2012-07-21T07:32:04-07:00"},{"id":"a2d244ec062f3348f6cd1c5218c6097402c5f562","short_id":"a2d244ec062","title":"Handle LDAP missing credentials error with a flash message.","author_name":"Pat Thoyts","author_email":"patthoyts@users.sourceforge.net","created_at":"2012-07-21T01:04:05-07:00"},{"id":"8b7e404b5b6944e9c92cc270b2e5d0005781d49d","short_id":"8b7e404b5b6","title":"Up to 2.7.0","author_name":"randx","author_email":"dmitriy.zaporozhets@gmail.com","created_at":"2012-07-21T00:53:55-07:00"},{"id":"11721b0dbe82c35789be3e4fa8e14663934b2ff5","short_id":"11721b0dbe8","title":"Help section for system hooks completed","author_name":"randx","author_email":"dmitriy.zaporozhets@gmail.com","created_at":"2012-07-21T00:47:57-07:00"},{"id":"9c8a1e651716212cf50a623d98e03b8dbdb2c64a","short_id":"9c8a1e65171","title":"Fix system hook example","author_name":"randx","author_email":"dmitriy.zaporozhets@gmail.com","created_at":"2012-07-21T00:32:42-07:00"},{"id":"4261acda90ff4c61326d80cba026ae76e8551f8f","short_id":"4261acda90f","title":"move SSH keys tab closer to begining","author_name":"randx","author_email":"dmitriy.zaporozhets@gmail.com","created_at":"2012-07-21T00:27:09-07:00"},{"id":"a69fc5dd23bd502fd36892a80eec21a4c53891f8","short_id":"a69fc5dd23b","title":"Endless event loading for dsahboard","author_name":"randx","author_email":"dmitriy.zaporozhets@gmail.com","created_at":"2012-07-21T00:23:05-07:00"},{"id":"860fa1163a5fbdfec2bb01ff2d584351554dee29","short_id":"860fa1163a5","title":"Merge pull request #1117 from patthoyts/pt/user-form","author_name":"Dmitriy Zaporozhets","author_email":"dmitriy.zaporozhets@gmail.com","created_at":"2012-07-20T14:23:49-07:00"},{"id":"787e5e94acf5e20280416c9fda105ef5b77576b3","short_id":"787e5e94acf","title":"Fix english on the edit user form.","author_name":"Pat Thoyts","author_email":"patthoyts@users.sourceforge.net","created_at":"2012-07-20T14:18:42-07:00"},{"id":"9267cb04b0b3fdf127899c4b7e636dc27fac06d3","short_id":"9267cb04b0b","title":"Merge branch 'refactoring_controllers' of dev.gitlabhq.com:gitlabhq","author_name":"Dmitriy Zaporozhets","author_email":"dmitriy.zaporozhets@gmail.com","created_at":"2012-07-20T07:24:56-07:00"}] \ No newline at end of file diff --git a/spec/fixtures/project_hook.json b/spec/fixtures/project_hook.json new file mode 100644 index 000000000..180dd4555 --- /dev/null +++ b/spec/fixtures/project_hook.json @@ -0,0 +1 @@ +{"id":1,"url":"https://api.example.net/v1/webhooks/ci"} diff --git a/spec/fixtures/project_hooks.json b/spec/fixtures/project_hooks.json new file mode 100644 index 000000000..e70d4122c --- /dev/null +++ b/spec/fixtures/project_hooks.json @@ -0,0 +1 @@ +[{"id":1,"url":"https://api.example.net/v1/webhooks/ci"}] \ No newline at end of file diff --git a/spec/fixtures/project_issues.json b/spec/fixtures/project_issues.json new file mode 100644 index 000000000..87fb2fb18 --- /dev/null +++ b/spec/fixtures/project_issues.json @@ -0,0 +1 @@ +[{"id":36,"project_id":3,"title":"Eos ut modi et laudantium quasi porro voluptas sed.","description":null,"labels":[],"milestone":null,"assignee":{"id":5,"email":"aliza_stark@schmeler.info","name":"Michale Von","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"author":{"id":5,"email":"aliza_stark@schmeler.info","name":"Michale Von","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"closed":false,"updated_at":"2012-09-17T09:42:20Z","created_at":"2012-09-17T09:42:20Z"},{"id":35,"project_id":3,"title":"Ducimus illo in iure voluptatem dolores labore.","description":null,"labels":[],"milestone":null,"assignee":{"id":4,"email":"nicole@mertz.com","name":"Felipe Davis","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"author":{"id":4,"email":"nicole@mertz.com","name":"Felipe Davis","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"closed":false,"updated_at":"2012-09-17T09:42:20Z","created_at":"2012-09-17T09:42:20Z"},{"id":34,"project_id":3,"title":"Rem tempora voluptatum atque eum sit nihil neque.","description":null,"labels":[],"milestone":null,"assignee":{"id":3,"email":"wilma@mayerblanda.ca","name":"Beatrice Jewess","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"author":{"id":3,"email":"wilma@mayerblanda.ca","name":"Beatrice Jewess","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"closed":false,"updated_at":"2012-09-17T09:42:20Z","created_at":"2012-09-17T09:42:20Z"},{"id":33,"project_id":3,"title":"Beatae possimus nostrum nihil reiciendis laboriosam nihil delectus alias accusantium dolor unde.","description":null,"labels":[],"milestone":null,"assignee":{"id":2,"email":"jack@example.com","name":"Jack Smith","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"author":{"id":2,"email":"jack@example.com","name":"Jack Smith","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"closed":false,"updated_at":"2012-09-17T09:42:20Z","created_at":"2012-09-17T09:42:20Z"},{"id":32,"project_id":3,"title":"Deserunt tenetur impedit est beatae voluptas voluptas quaerat quisquam.","description":null,"labels":[],"milestone":null,"assignee":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"author":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"closed":false,"updated_at":"2012-09-17T09:42:20Z","created_at":"2012-09-17T09:42:20Z"},{"id":16,"project_id":3,"title":"Numquam earum aut laudantium reprehenderit voluptatem aut.","description":null,"labels":[],"milestone":null,"assignee":{"id":5,"email":"aliza_stark@schmeler.info","name":"Michale Von","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"author":{"id":5,"email":"aliza_stark@schmeler.info","name":"Michale Von","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"closed":false,"updated_at":"2012-09-17T09:42:20Z","created_at":"2012-09-17T09:42:20Z"},{"id":15,"project_id":3,"title":"Qui veritatis voluptas fuga voluptate voluptas cupiditate.","description":null,"labels":[],"milestone":null,"assignee":{"id":4,"email":"nicole@mertz.com","name":"Felipe Davis","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"author":{"id":4,"email":"nicole@mertz.com","name":"Felipe Davis","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"closed":false,"updated_at":"2012-09-17T09:42:20Z","created_at":"2012-09-17T09:42:20Z"},{"id":14,"project_id":3,"title":"In assumenda et ipsa qui debitis voluptatem incidunt.","description":null,"labels":[],"milestone":null,"assignee":{"id":3,"email":"wilma@mayerblanda.ca","name":"Beatrice Jewess","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"author":{"id":3,"email":"wilma@mayerblanda.ca","name":"Beatrice Jewess","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"closed":false,"updated_at":"2012-09-17T09:42:20Z","created_at":"2012-09-17T09:42:20Z"},{"id":13,"project_id":3,"title":"Illo eveniet consequatur enim iste provident facilis rerum voluptatem et architecto aut.","description":null,"labels":[],"milestone":null,"assignee":{"id":2,"email":"jack@example.com","name":"Jack Smith","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"author":{"id":2,"email":"jack@example.com","name":"Jack Smith","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"closed":false,"updated_at":"2012-09-17T09:42:20Z","created_at":"2012-09-17T09:42:20Z"},{"id":12,"project_id":3,"title":"Veniam et tempore quidem eum reprehenderit cupiditate non aut velit eaque.","description":null,"labels":[],"milestone":null,"assignee":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"author":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"closed":false,"updated_at":"2012-09-17T09:42:20Z","created_at":"2012-09-17T09:42:20Z"}] \ No newline at end of file diff --git a/spec/fixtures/project_tags.json b/spec/fixtures/project_tags.json new file mode 100644 index 000000000..1e2fb96cb --- /dev/null +++ b/spec/fixtures/project_tags.json @@ -0,0 +1 @@ +[{"name":"v2.8.2","commit":{"id":"a502f67c0b358cc6b391df0c5dca48375c21fcad","parents":[{"id":"4381084af341684240b1a671d368511afcf5774a"}],"tree":"1612068bdd20de5d14b3096cfa4c621e2051ed4c","message":"Up to 2.8.2","author":{"name":"randx","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"randx","email":"dmitriy.zaporozhets@gmail.com"},"authored_date":"2012-08-24T02:03:48-07:00","committed_date":"2012-08-24T02:03:48-07:00"}},{"name":"v2.8.1","commit":{"id":"ed2b53cd1c34c421b23208eeb502a141a6829f9d","parents":[{"id":"7ab587a47791e371f5c109c14097a5d1d7776ea5"}],"tree":"b7393b0b33b777583b285e85b423c4e5ab7f859f","message":"Up to 2.8.1","author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"authored_date":"2012-08-22T23:17:18-07:00","committed_date":"2012-08-22T23:17:18-07:00"}},{"name":"v2.8.0pre","commit":{"id":"b2c6ba97a25d299e83c51493d7bc770c13b8ed1a","parents":[{"id":"05da3801f53f06fdc529b4f3820af1380039f245"},{"id":"66399d558da45fb9cd3ea972a47a4f7bb12bfc8d"}],"tree":"36ad53f35bce1fe3f2a4a5f840e7b1bdbfed9c82","message":"Merge pull request #1230 from tsigo/hooray_apostrophes\n\nCorrect usage of \"Can't\"","author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"authored_date":"2012-08-16T14:11:08-07:00","committed_date":"2012-08-16T14:11:08-07:00"}},{"name":"v2.8.0","commit":{"id":"5c7ed6fa26b47ac71ff6ba04720d85df6d74b200","parents":[{"id":"d1daeba1736ba145fe525ce08a91f29495a3abf1"}],"tree":"4fc230ff2dbc0e75f27321eac2976aba5a6d323d","message":"Up to 2.8","author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"authored_date":"2012-08-21T15:15:26-07:00","committed_date":"2012-08-21T15:15:26-07:00"}},{"name":"v2.7.0pre","commit":{"id":"72a571724d84d112f98a5543c971e9b3b9da1383","parents":[{"id":"3ac840ff06e0ee5b349c52b5a8c02e803a17eec3"},{"id":"990b9217d9a55e26a53d4143d4a3c89123384327"}],"tree":"64b104df5d956e21e0749dc8e70849d1989de36f","message":"Merge pull request #1096 from moregeek/show-flash-note-when-destroying-a-project\n\nshow flash notice after deletion of a project","author":{"name":"Valeriy Sizov","email":"vsv2711@gmail.com"},"committer":{"name":"Valeriy Sizov","email":"vsv2711@gmail.com"},"authored_date":"2012-07-18T05:35:42-07:00","committed_date":"2012-07-18T05:35:42-07:00"}},{"name":"v2.7.0","commit":{"id":"8b7e404b5b6944e9c92cc270b2e5d0005781d49d","parents":[{"id":"11721b0dbe82c35789be3e4fa8e14663934b2ff5"}],"tree":"89fe8c5ff58daaedea07a910cffb14b04ebcc828","message":"Up to 2.7.0","author":{"name":"randx","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"randx","email":"dmitriy.zaporozhets@gmail.com"},"authored_date":"2012-07-21T00:53:55-07:00","committed_date":"2012-07-21T00:53:55-07:00"}},{"name":"v2.6.3","commit":{"id":"666cdb22792dd955a286b9993d6235b4cdd68b4b","parents":[{"id":"d92446df1fdba87101c92c90b1c34eb2f1eebef4"}],"tree":"888173aa4c12a4920d318c35b950095d3505673d","message":"up to 2.6.3","author":{"name":"randx","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"randx","email":"dmitriy.zaporozhets@gmail.com"},"authored_date":"2012-06-26T09:20:47-07:00","committed_date":"2012-06-26T09:21:28-07:00"}},{"name":"v2.6.2","commit":{"id":"39fecb554f172a0c8ea00316e612e1d37efc7200","parents":[{"id":"68389588d664100590b1a6ca7eedd50860b7e9bc"}],"tree":"53accb25e0b9d038d550cf387753bde15fe4ad19","message":"Up to 2.6.2","author":{"name":"randx","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"randx","email":"dmitriy.zaporozhets@gmail.com"},"authored_date":"2012-06-22T13:50:58-07:00","committed_date":"2012-06-22T13:50:58-07:00"}},{"name":"v2.6.1","commit":{"id":"d92a22c9e627268eca697bbd9b660d8c335df953","parents":[{"id":"193804516b8b0783c850981456e947f888ff51bb"}],"tree":"4ac1b5225f597ab55372cb5e950b121d6f55e386","message":"Up to 2.6.1","author":{"name":"randx","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"randx","email":"dmitriy.zaporozhets@gmail.com"},"authored_date":"2012-06-22T12:49:03-07:00","committed_date":"2012-06-22T12:49:03-07:00"}},{"name":"v2.6.0","commit":{"id":"b32465712becfbcf83d63b1e6eff7d1483fdabea","parents":[{"id":"1903f6ade027df0f10ef96b9439495eeda07482c"}],"tree":"ffbc05fd0f1771c1602c956df9556260048c7167","message":"Up to 2.6","author":{"name":"randx","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"randx","email":"dmitriy.zaporozhets@gmail.com"},"authored_date":"2012-06-21T10:25:23-07:00","committed_date":"2012-06-21T10:25:23-07:00"}},{"name":"v2.5.0","commit":{"id":"cc8369144db2147d2956e8dd7d314e9a7dfd4fbb","parents":[{"id":"1b2068eaa91e5002d01a220c65da21dad8ccb071"}],"tree":"666a442e00689911169e8cc336c5ce60d014854c","message":"Prevent app crash in case if encoding failed","author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"authored_date":"2012-05-22T04:57:04-07:00","committed_date":"2012-05-22T04:57:04-07:00"}},{"name":"v2.4.2","commit":{"id":"f18339c26d673c5f8b4c19776036fd42a0de30aa","parents":[{"id":"c937d06c3c98e9ffce8ec1132203eaff6bf7b231"},{"id":"35e602f19c83585d64aa2043ed26eeb8cd7b40e2"}],"tree":"5101f0cd8e395fee1996764298a202437757e85b","message":"Merge branch 'master' of github.com:gitlabhq/gitlabhq","author":{"name":"Zevs","email":"vsv2711@gmail.com"},"committer":{"name":"Zevs","email":"vsv2711@gmail.com"},"authored_date":"2012-04-29T14:24:59-07:00","committed_date":"2012-04-29T14:24:59-07:00"}},{"name":"v2.4.1","commit":{"id":"d97a9aa4a44ff9f452144fad348fd9d7e3b48260","parents":[{"id":"21f3da23589d50038728393f0badc6255b5762ca"}],"tree":"905c33874b064778199f806749d5688e33d64be3","message":"fixed email markdown","author":{"name":"gitlabhq","email":"m@gitlabhq.com"},"committer":{"name":"gitlabhq","email":"m@gitlabhq.com"},"authored_date":"2012-04-23T05:32:56-07:00","committed_date":"2012-04-23T05:32:56-07:00"}},{"name":"v2.4.0pre","commit":{"id":"1845429268364e75bffdeb1075de8f1606e157ec","parents":[{"id":"45b18365d5f409f196a02a4e6e2b77b8ebef909b"}],"tree":"423c70246fa7ffd8804b26628fea34bdb2b22846","message":"Use try for commit prev_commit_id detection","author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"authored_date":"2012-04-19T13:35:35-07:00","committed_date":"2012-04-19T13:35:35-07:00"}},{"name":"v2.4.0","commit":{"id":"204c66461ed519eb0078be7e8ac8a6cb56834753","parents":[{"id":"511d07c47c9bf3a18bfa276d452c899369432a22"}],"tree":"9416c777cccf87d348f5705078e82f3f97485e19","message":"corrected exception for automerge","author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"authored_date":"2012-04-22T06:49:45-07:00","committed_date":"2012-04-22T06:49:45-07:00"}},{"name":"v2.3.1","commit":{"id":"fa8219e0a753e642a6f1dbdfc010d01ae8a949ee","parents":[{"id":"81da8e46f24913ccf42d3e2644962cbcbc0f9c2e"}],"tree":"5debfcd6d17f9d582aace6ac9b80db27d5c1fe36","message":"better MR list, dashboard pollished","author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"authored_date":"2012-03-22T13:57:04-07:00","committed_date":"2012-03-22T13:57:04-07:00"}},{"name":"v2.3.0pre","commit":{"id":"cadf12c60cc27c5b0b8273c1de4b190a0e88bd7d","parents":[{"id":"724ea16c348bc61cf7cb3dbe362c6f30cff1b2c7"}],"tree":"6f4c22761fd2dee405d3fbf38f9dd835bb3c8694","message":"Merged activities & projects pages","author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"authored_date":"2012-03-19T15:05:35-07:00","committed_date":"2012-03-19T15:05:35-07:00"}},{"name":"v2.3.0","commit":{"id":"b57faf9282d7df6cdd62953d474652a0ae2e6896","parents":[{"id":"cadf12c60cc27c5b0b8273c1de4b190a0e88bd7d"}],"tree":"f0d5b826df373191b4681452fc2ae4c5970cef4a","message":"Push events polished","author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"authored_date":"2012-03-20T14:59:35-07:00","committed_date":"2012-03-20T14:59:35-07:00"}},{"name":"v2.2.0pre","commit":{"id":"6a445b42003007cbb6c06f477c4d7a0b175688c1","parents":[{"id":"22f4c1908d0fc2dbce02e74ed03bf65f028d78d6"}],"tree":"9c60577833f6ca717acdebfa66140124c88e8471","message":"fixed forgot password form","author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"authored_date":"2012-02-20T10:37:37-08:00","committed_date":"2012-02-20T10:37:37-08:00"}},{"name":"v2.2.0","commit":{"id":"9e6d0710e927aa8ea834b8a9ae9f277be617ac7d","parents":[{"id":"8c40aab120dbc5507ab9cc8d7ad8e2519d6e9f25"},{"id":"6ea87c47f0f8a24ae031c3fff17bc913889ecd00"}],"tree":"86c831ab21236f21ffa5b97c752369612ce41b39","message":"Merge pull request #443 from CedricGatay/fix/incorrectLineNumberingInDiff\n\nIncorrect line numbering in diff","author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"authored_date":"2012-02-22T07:14:54-08:00","committed_date":"2012-02-22T07:14:54-08:00"}},{"name":"v2.1.0","commit":{"id":"98d6492582d232ed86525aa31ccbf280f4cbdaef","parents":[{"id":"611c5a87ab0c083a43785323b09cc47f554c3ba4"}],"tree":"1689b3cad580a18fd9b429ee0b33dac21c9f5a48","message":"removed broken migration","author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"authored_date":"2012-01-22T10:52:06-08:00","committed_date":"2012-01-22T10:52:06-08:00"}},{"name":"v2.0.0","commit":{"id":"9a2a8612769d472503b367fa35e99f6fb2876704","parents":[{"id":"2f7b67161952fc9ab322eba6878511b5f2dd5cf1"}],"tree":"26cdb4e66b5e664fe4bcd57d011c54c9c9c26ded","message":"Design tab for profile. Colorscheme as db value","author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"authored_date":"2011-12-20T12:47:09-08:00","committed_date":"2011-12-20T12:47:09-08:00"}},{"name":"v1.2.2","commit":{"id":"139a332293b9d8c4e5436619036e093483d8347f","parents":[{"id":"ade12da9488bea19d12505c371ead35686a1436e"}],"tree":"365d57f4df5c5dcac69b666cf6d2bfd8ef058008","message":"updated readme","author":{"name":"Dmitriy Zaporozhets","email":"dzaporozhets@sphereconsultinginc.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dzaporozhets@sphereconsultinginc.com"},"authored_date":"2011-11-25T14:30:51-08:00","committed_date":"2011-11-25T14:30:51-08:00"}},{"name":"v1.2.1","commit":{"id":"7ebba27db21719c0035bab65fea92a4780051c73","parents":[{"id":"b56024100d40457a998f83adae3cdc830c997cda"},{"id":"a4fbe13fce87cb6ff2a27a2574ae25bf1dad145c"}],"tree":"b121a7576af1503a96954ce9a94598a68579e053","message":"Merge branch 'master' of dev.gitlabhq.com:gitlabhq","author":{"name":"Dmitriy Zaporozhets","email":"dzaporozhets@sphereconsultinginc.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dzaporozhets@sphereconsultinginc.com"},"authored_date":"2011-11-22T13:15:09-08:00","committed_date":"2011-11-22T13:15:09-08:00"}},{"name":"v1.2.0pre","commit":{"id":"86829cae50857b5edf74b935380c6f68a19c2282","parents":[{"id":"a6b99319381c2d62ec4b92d64805e8de8965859e"}],"tree":"6aab9d13000584fa96fb3cb34d94f3b122bd1143","message":"fixed min height for menu","author":{"name":"gitlabhq","email":"m@gitlabhq.com"},"committer":{"name":"gitlabhq","email":"m@gitlabhq.com"},"authored_date":"2011-11-22T06:03:27-08:00","committed_date":"2011-11-22T06:03:27-08:00"}},{"name":"v1.2.0","commit":{"id":"b56024100d40457a998f83adae3cdc830c997cda","parents":[{"id":"4451b8df8ad6d4b6d79fbce77687c6c2fd37d0a9"}],"tree":"f402cbb6d54526a32b30968c98410bae97b27c8d","message":"lil style fixes","author":{"name":"Dmitriy Zaporozhets","email":"dzaporozhets@sphereconsultinginc.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dzaporozhets@sphereconsultinginc.com"},"authored_date":"2011-11-22T09:57:25-08:00","committed_date":"2011-11-22T09:57:25-08:00"}},{"name":"v1.1.0pre","commit":{"id":"6b030fd41d697e327d2935b406cba70b6a460504","parents":[{"id":"3a2b273316fb29d63b489906f85d9b5329377258"}],"tree":"63b1fdb2a0f135f7074f6a94da14543b8450dd71","message":"1.1pre1","author":{"name":"Dmitriy Zaporozhets","email":"dzaporozhets@sphereconsultinginc.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dzaporozhets@sphereconsultinginc.com"},"authored_date":"2011-10-21T10:04:41-07:00","committed_date":"2011-10-21T10:04:41-07:00"}},{"name":"v1.1.0","commit":{"id":"ba8048d71019b5aaa1f92ee5c3415bfddaa9babb","parents":[{"id":"6b030fd41d697e327d2935b406cba70b6a460504"}],"tree":"4db2b5f4f9b374dd1be3579459bc5947c225c9ba","message":"v1.1.0","author":{"name":"Dmitriy Zaporozhets","email":"dzaporozhets@sphereconsultinginc.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dzaporozhets@sphereconsultinginc.com"},"authored_date":"2011-10-22T06:07:26-07:00","committed_date":"2011-10-22T06:07:26-07:00"}},{"name":"v1.0.2","commit":{"id":"3a2b273316fb29d63b489906f85d9b5329377258","parents":[{"id":"757ea634665e475bf69c1ec962040a0511ee8aeb"},{"id":"c374eb80ff9fb71d37faffc15714bf98b632d3e5"}],"tree":"e0d8170e61a9468a7bb5d4e63305171ec1efa6bf","message":"Merge pull request #40 from vslinko/patch-1\n\nIncrease max key length. Some keys has comment after key string.","author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"authored_date":"2011-10-18T23:30:06-07:00","committed_date":"2011-10-18T23:30:06-07:00"}},{"name":"v1.0.1","commit":{"id":"7b5799a97998b68416f1b6233ce427135c99165a","parents":[{"id":"0541b3f3c5dcd291d144c83d9731c75ee811b4e0"},{"id":"7b67480c76db8b9a9ccdc80015cc500dc6d26892"}],"tree":"e052185e9dd72a1b1a04d59a5f9efbf3c0369601","message":"Merge branch '1x' of github.com:gitlabhq/gitlabhq into 1x","author":{"name":"Dmitriy Zaporozhets","email":"dzaporozhets@sphereconsultinginc.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dzaporozhets@sphereconsultinginc.com"},"authored_date":"2011-10-14T15:16:44-07:00","committed_date":"2011-10-14T15:16:44-07:00"}}] \ No newline at end of file diff --git a/spec/fixtures/projects.json b/spec/fixtures/projects.json new file mode 100644 index 000000000..deab4c5f3 --- /dev/null +++ b/spec/fixtures/projects.json @@ -0,0 +1 @@ +[{"id":1,"code":"brute","name":"Brute","description":null,"path":"brute","default_branch":null,"owner":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"private":true,"issues_enabled":true,"merge_requests_enabled":true,"wall_enabled":true,"wiki_enabled":true,"created_at":"2012-09-17T09:41:56Z"},{"id":2,"code":"mozart","name":"Mozart","description":null,"path":"mozart","default_branch":null,"owner":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"private":true,"issues_enabled":true,"merge_requests_enabled":true,"wall_enabled":true,"wiki_enabled":true,"created_at":"2012-09-17T09:41:57Z"},{"id":3,"code":"gitlab","name":"Gitlab","description":null,"path":"gitlab","default_branch":null,"owner":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"private":true,"issues_enabled":true,"merge_requests_enabled":true,"wall_enabled":true,"wiki_enabled":true,"created_at":"2012-09-17T09:41:58Z"}] \ No newline at end of file diff --git a/spec/fixtures/session.json b/spec/fixtures/session.json new file mode 100644 index 000000000..e4f5ba35f --- /dev/null +++ b/spec/fixtures/session.json @@ -0,0 +1 @@ +{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z","private_token":"qEsq1pt6HJPaNciie3MG"} \ No newline at end of file diff --git a/spec/fixtures/single_user.json b/spec/fixtures/single_user.json new file mode 100644 index 000000000..a5c0e0d3b --- /dev/null +++ b/spec/fixtures/single_user.json @@ -0,0 +1 @@ +{"id":2,"email":"jack@example.com","name":"Jack Smith","bio":null,"skype":"","linkedin":"","twitter":"","dark_scheme":false,"theme_id":1,"blocked":false,"created_at":"2012-09-17T09:42:03Z"} \ No newline at end of file diff --git a/spec/fixtures/snippet.json b/spec/fixtures/snippet.json new file mode 100644 index 000000000..34e9d994d --- /dev/null +++ b/spec/fixtures/snippet.json @@ -0,0 +1 @@ +{"id":1,"title":"Rails Console ActionMailer","file_name":"mailer_test.rb","author":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"expires_at":"2012-09-24T00:00:00Z","updated_at":"2012-09-17T09:51:42Z","created_at":"2012-09-17T09:51:42Z"} \ No newline at end of file diff --git a/spec/fixtures/team_member.json b/spec/fixtures/team_member.json new file mode 100644 index 000000000..fd3ac3852 --- /dev/null +++ b/spec/fixtures/team_member.json @@ -0,0 +1 @@ +{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z","access_level":40} \ No newline at end of file diff --git a/spec/fixtures/team_members.json b/spec/fixtures/team_members.json new file mode 100644 index 000000000..a2fe19e3b --- /dev/null +++ b/spec/fixtures/team_members.json @@ -0,0 +1 @@ +[{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z","access_level":40},{"id":2,"email":"jack@example.com","name":"Jack Smith","blocked":false,"created_at":"2012-09-17T09:42:03Z","access_level":20},{"id":3,"email":"wilma@mayerblanda.ca","name":"Beatrice Jewess","blocked":false,"created_at":"2012-09-17T09:42:03Z","access_level":40},{"id":5,"email":"aliza_stark@schmeler.info","name":"Michale Von","blocked":false,"created_at":"2012-09-17T09:42:03Z","access_level":40},{"id":6,"email":"faye.watsica@rohanwalter.com","name":"Ambrose Hansen","blocked":false,"created_at":"2012-09-17T09:42:03Z","access_level":40},{"id":7,"email":"maida@walshtorp.name","name":"Alana Hahn","blocked":false,"created_at":"2012-09-17T09:42:03Z","access_level":20}] \ No newline at end of file diff --git a/spec/fixtures/user.json b/spec/fixtures/user.json new file mode 100644 index 000000000..4e0daca50 --- /dev/null +++ b/spec/fixtures/user.json @@ -0,0 +1 @@ +{"id":1,"email":"john@example.com","name":"John Smith","bio":null,"skype":"","linkedin":"","twitter":"john","dark_scheme":false,"theme_id":1,"blocked":false,"created_at":"2012-09-17T09:41:56Z"} \ No newline at end of file diff --git a/spec/fixtures/users.json b/spec/fixtures/users.json new file mode 100644 index 000000000..14c6388bf --- /dev/null +++ b/spec/fixtures/users.json @@ -0,0 +1 @@ +[{"id":1,"email":"john@example.com","name":"John Smith","bio":null,"skype":"","linkedin":"","twitter":"john","dark_scheme":false,"theme_id":1,"blocked":false,"created_at":"2012-09-17T09:41:56Z"},{"id":2,"email":"jack@example.com","name":"Jack Smith","bio":null,"skype":"","linkedin":"","twitter":"","dark_scheme":false,"theme_id":1,"blocked":false,"created_at":"2012-09-17T09:42:03Z"},{"id":3,"email":"wilma@mayerblanda.ca","name":"Beatrice Jewess","bio":null,"skype":"","linkedin":"","twitter":"","dark_scheme":false,"theme_id":1,"blocked":false,"created_at":"2012-09-17T09:42:03Z"},{"id":4,"email":"nicole@mertz.com","name":"Felipe Davis","bio":null,"skype":"","linkedin":"","twitter":"","dark_scheme":false,"theme_id":1,"blocked":false,"created_at":"2012-09-17T09:42:03Z"},{"id":5,"email":"aliza_stark@schmeler.info","name":"Michale Von","bio":null,"skype":"","linkedin":"","twitter":"","dark_scheme":false,"theme_id":1,"blocked":false,"created_at":"2012-09-17T09:42:03Z"},{"id":6,"email":"faye.watsica@rohanwalter.com","name":"Ambrose Hansen","bio":null,"skype":"","linkedin":"","twitter":"","dark_scheme":false,"theme_id":1,"blocked":false,"created_at":"2012-09-17T09:42:03Z"},{"id":7,"email":"maida@walshtorp.name","name":"Alana Hahn","bio":null,"skype":"","linkedin":"","twitter":"","dark_scheme":false,"theme_id":1,"blocked":false,"created_at":"2012-09-17T09:42:03Z"}] \ No newline at end of file diff --git a/spec/gitlab/client/issues_spec.rb b/spec/gitlab/client/issues_spec.rb new file mode 100644 index 000000000..eaa3257f2 --- /dev/null +++ b/spec/gitlab/client/issues_spec.rb @@ -0,0 +1,88 @@ +require 'spec_helper' + +describe Gitlab::Client do + describe ".issues" do + context "with project ID passed" do + before do + stub_get("/projects/3/issues", "project_issues") + @issues = Gitlab.issues(3) + end + + it "should get the correct resource" do + a_get("/projects/3/issues").should have_been_made + end + + it "should return an array of project's issues" do + @issues.should be_an Array + @issues.first.project_id.should == 3 + end + end + + context "without project ID passed" do + before do + stub_get("/issues", "issues") + @issues = Gitlab.issues + end + + it "should get the correct resource" do + a_get("/issues").should have_been_made + end + + it "should return an array of user's issues" do + @issues.should be_an Array + @issues.first.closed.should be_false + @issues.first.author.name.should == "John Smith" + end + end + end + + describe ".issue" do + before do + stub_get("/projects/3/issues/33", "issue") + @issue = Gitlab.issue(3, 33) + end + + it "should get the correct resource" do + a_get("/projects/3/issues/33").should have_been_made + end + + it "should return information about an issue" do + @issue.project_id.should == 3 + @issue.assignee.name.should == "Jack Smith" + end + end + + describe ".create_issue" do + before do + stub_post("/projects/3/issues", "issue") + @issue = Gitlab.create_issue(3, 'title') + end + + it "should get the correct resource" do + a_post("/projects/3/issues"). + with(:body => {:title => 'title'}).should have_been_made + end + + it "should return information about a created issue" do + @issue.project_id.should == 3 + @issue.assignee.name.should == "Jack Smith" + end + end + + describe ".edit_issue" do + before do + stub_put("/projects/3/issues/33", "issue") + @issue = Gitlab.edit_issue(3, 33, :title => 'title') + end + + it "should get the correct resource" do + a_put("/projects/3/issues/33"). + with(:body => {:title => 'title'}).should have_been_made + end + + it "should return information about an edited issue" do + @issue.project_id.should == 3 + @issue.assignee.name.should == "Jack Smith" + end + end +end diff --git a/spec/gitlab/client/milestones_spec.rb b/spec/gitlab/client/milestones_spec.rb new file mode 100644 index 000000000..3ceed96ec --- /dev/null +++ b/spec/gitlab/client/milestones_spec.rb @@ -0,0 +1,66 @@ +require 'spec_helper' + +describe Gitlab::Client do + describe ".milestones" do + before do + stub_get("/projects/3/milestones", "milestones") + @milestones = Gitlab.milestones(3) + end + + it "should get the correct resource" do + a_get("/projects/3/milestones").should have_been_made + end + + it "should return an array of project's milestones" do + @milestones.should be_an Array + @milestones.first.project_id.should == 3 + end + end + + describe ".milestone" do + before do + stub_get("/projects/3/milestones/1", "milestone") + @milestone = Gitlab.milestone(3, 1) + end + + it "should get the correct resource" do + a_get("/projects/3/milestones/1").should have_been_made + end + + it "should return information about a milestone" do + @milestone.project_id.should == 3 + end + end + + describe ".create_milestone" do + before do + stub_post("/projects/3/milestones", "milestone") + @milestone = Gitlab.create_milestone(3, 'title') + end + + it "should get the correct resource" do + a_post("/projects/3/milestones"). + with(:body => {:title => 'title'}).should have_been_made + end + + it "should return information about a created milestone" do + @milestone.project_id.should == 3 + end + end + + describe ".edit_milestone" do + before do + stub_put("/projects/3/milestones/33", "milestone") + @milestone = Gitlab.edit_milestone(3, 33, :title => 'title') + end + + it "should get the correct resource" do + a_put("/projects/3/milestones/33"). + with(:body => {:title => 'title'}).should have_been_made + end + + it "should return information about an edited milestone" do + @milestone.project_id.should == 3 + end + end +end diff --git a/spec/gitlab/client/projects_spec.rb b/spec/gitlab/client/projects_spec.rb new file mode 100644 index 000000000..058297819 --- /dev/null +++ b/spec/gitlab/client/projects_spec.rb @@ -0,0 +1,177 @@ +require 'spec_helper' + +describe Gitlab::Client do + describe ".projects" do + before do + stub_get("/projects", "projects") + @projects = Gitlab.projects + end + + it "should get the correct resource" do + a_get("/projects").should have_been_made + end + + it "should return an array of projects" do + @projects.should be_an Array + @projects.first.name.should == "Brute" + @projects.first.owner.name.should == "John Smith" + end + end + + describe ".project" do + before do + stub_get("/projects/3", "project") + @project = Gitlab.project(3) + end + + it "should get the correct resource" do + a_get("/projects/3").should have_been_made + end + + it "should return information about a project" do + @project.name.should == "Gitlab" + @project.owner.name.should == "John Smith" + end + end + + describe ".create_project" do + before do + stub_post("/projects", "project") + @project = Gitlab.create_project('Gitlab') + end + + it "should get the correct resource" do + a_post("/projects").should have_been_made + end + + it "should return information about a project" do + @project.name.should == "Gitlab" + @project.owner.name.should == "John Smith" + end + end + + describe ".team_members" do + before do + stub_get("/projects/3/members", "team_members") + @team_members = Gitlab.team_members(3) + end + + it "should get the correct resource" do + a_get("/projects/3/members").should have_been_made + end + + it "should return an array of team members" do + @team_members.should be_an Array + @team_members.first.name.should == "John Smith" + end + end + + describe ".team_member" do + before do + stub_get("/projects/3/members/1", "team_member") + @team_member = Gitlab.team_member(3, 1) + end + + it "should get the correct resource" do + a_get("/projects/3/members/1").should have_been_made + end + + it "should return information about a team member" do + @team_member.name.should == "John Smith" + end + end + + describe ".add_team_member" do + before do + stub_post("/projects/3/members/1", "team_member") + @team_member = Gitlab.add_team_member(3, 1, 40) + end + + it "should get the correct resource" do + a_post("/projects/3/members/1"). + with(:body => {:access_level => '40'}).should have_been_made + end + + it "should return information about a team member" do + @team_member.name.should == "John Smith" + end + end + + describe ".edit_team_member" do + before do + stub_put("/projects/3/members/1", "team_member") + @team_member = Gitlab.edit_team_member(3, 1, 40) + end + + it "should get the correct resource" do + a_put("/projects/3/members/1"). + with(:body => {:access_level => '40'}).should have_been_made + end + + it "should return information about a team member" do + @team_member.name.should == "John Smith" + end + end + + describe ".remove_team_member" do + before do + stub_delete("/projects/3/members/1", "team_member") + @team_member = Gitlab.remove_team_member(3, 1) + end + + it "should get the correct resource" do + a_delete("/projects/3/members/1").should have_been_made + end + + it "should return information about a team member" do + @team_member.name.should == "John Smith" + end + end + + describe ".project_hooks" do + before do + stub_get("/projects/1/hooks", "project_hooks") + @hooks = Gitlab.project_hooks(1) + end + + it "should get the correct resource" do + a_get("/projects/1/hooks").should have_been_made + end + + it "should return an array of hooks" do + @hooks.should be_an Array + @hooks.first.url.should == "https://api.example.net/v1/webhooks/ci" + end + end + + describe ".add_project_hook" do + before do + stub_post("/projects/1/hooks", "project_hook") + @hook = Gitlab.add_project_hook(1, "https://api.example.net/v1/webhooks/ci") + end + + it "should get the correct resource" do + body = {:url => "https://api.example.net/v1/webhooks/ci"} + a_post("/projects/1/hooks").with(:body => body).should have_been_made + end + + it "should return information about an added hook" do + @hook.url.should == "https://api.example.net/v1/webhooks/ci" + end + end + + describe ".delete_project_hook" do + before do + stub_delete("/projects/1/hooks/1", "project_hook") + @hook = Gitlab.delete_project_hook(1, 1) + end + + it "should get the correct resource" do + a_delete("/projects/1/hooks/1").should have_been_made + end + + it "should return information about a deleted hook" do + @hook.url.should == "https://api.example.net/v1/webhooks/ci" + end + end +end diff --git a/spec/gitlab/client/repositories_spec.rb b/spec/gitlab/client/repositories_spec.rb new file mode 100644 index 000000000..296d6447d --- /dev/null +++ b/spec/gitlab/client/repositories_spec.rb @@ -0,0 +1,73 @@ +require 'spec_helper' + +describe Gitlab::Client do + it { should respond_to :repo_tags } + it { should respond_to :repo_branches } + it { should respond_to :repo_branch } + it { should respond_to :repo_commits } + + describe ".tags" do + before do + stub_get("/projects/3/repository/tags", "project_tags") + @tags = Gitlab.tags(3) + end + + it "should get the correct resource" do + a_get("/projects/3/repository/tags").should have_been_made + end + + it "should return an array of repository tags" do + @tags.should be_an Array + @tags.first.name.should == "v2.8.2" + end + end + + describe ".branches" do + before do + stub_get("/projects/3/repository/branches", "project_branches") + @branches = Gitlab.branches(3) + end + + it "should get the correct resource" do + a_get("/projects/3/repository/branches").should have_been_made + end + + it "should return an array of repository branches" do + @branches.should be_an Array + @branches.first.name.should == "api" + end + end + + describe ".branch" do + before do + stub_get("/projects/3/repository/branches/api", "project_branch") + @branch = Gitlab.branch(3, "api") + end + + it "should get the correct resource" do + a_get("/projects/3/repository/branches/api").should have_been_made + end + + it "should return information about a repository branch" do + @branch.name.should == "api" + end + end + + describe ".commits" do + before do + stub_get("/projects/3/repository/commits", "project_commits"). + with(:query => {:ref_name => "api"}) + @commits = Gitlab.commits(3, :ref_name => "api") + end + + it "should get the correct resource" do + a_get("/projects/3/repository/commits"). + with(:query => {:ref_name => "api"}).should have_been_made + end + + it "should return an array of respository commits" do + @commits.should be_an Array + @commits.first.id.should == "f7dd067490fe57505f7226c3b54d3127d2f7fd46" + end + end +end diff --git a/spec/gitlab/client/snippets_spec.rb b/spec/gitlab/client/snippets_spec.rb new file mode 100644 index 000000000..01ef01cb1 --- /dev/null +++ b/spec/gitlab/client/snippets_spec.rb @@ -0,0 +1,69 @@ +require 'spec_helper' + +describe Gitlab::Client do + describe ".snippet" do + before do + stub_get("/projects/3/snippets/1", "snippet") + @snippet = Gitlab.snippet(3, 1) + end + + it "should get the correct resource" do + a_get("/projects/3/snippets/1").should have_been_made + end + + it "should return information about a snippet" do + @snippet.file_name.should == "mailer_test.rb" + @snippet.author.name.should == "John Smith" + end + end + + describe ".create_snippet" do + before do + stub_post("/projects/3/snippets", "snippet") + @snippet = Gitlab.create_snippet(3, {:title => 'API', :file_name => 'api.rb', :code => 'code'}) + end + + it "should get the correct resource" do + body = {:title => 'API', :file_name => 'api.rb', :code => 'code'} + a_post("/projects/3/snippets").with(:body => body).should have_been_made + end + + it "should return information about a new snippet" do + @snippet.file_name.should == "mailer_test.rb" + @snippet.author.name.should == "John Smith" + end + end + + describe ".edit_snippet" do + before do + stub_put("/projects/3/snippets/1", "snippet") + @snippet = Gitlab.edit_snippet(3, 1, :file_name => 'mailer_test.rb') + end + + it "should get the correct resource" do + a_put("/projects/3/snippets/1"). + with(:body => {:file_name => 'mailer_test.rb'}).should have_been_made + end + + it "should return information about an edited snippet" do + @snippet.file_name.should == "mailer_test.rb" + @snippet.author.name.should == "John Smith" + end + end + + describe ".delete_snippet" do + before do + stub_delete("/projects/3/snippets/1", "snippet") + @snippet = Gitlab.delete_snippet(3, 1) + end + + it "should get the correct resource" do + a_delete("/projects/3/snippets/1").should have_been_made + end + + it "should return information about a deleted snippet" do + @snippet.file_name.should == "mailer_test.rb" + @snippet.author.name.should == "John Smith" + end + end +end diff --git a/spec/gitlab/client/users_spec.rb b/spec/gitlab/client/users_spec.rb new file mode 100644 index 000000000..8a40ddd9e --- /dev/null +++ b/spec/gitlab/client/users_spec.rb @@ -0,0 +1,129 @@ +require 'spec_helper' + +describe Gitlab::Client do + describe ".users" do + before do + stub_get("/users", "users") + @users = Gitlab.users + end + + it "should get the correct resource" do + a_get("/users").should have_been_made + end + + it "should return an array of users" do + @users.should be_an Array + @users.first.email.should == "john@example.com" + end + end + + describe ".user" do + context "with user ID passed" do + before do + stub_get("/users/2", "single_user") + @user = Gitlab.user(2) + end + + it "should get the correct resource" do + a_get("/users/2").should have_been_made + end + + it "should return information about a user" do + @user.email.should == "jack@example.com" + end + end + + context "without user ID passed" do + before do + stub_get("/user", "user") + @user = Gitlab.user + end + + it "should get the correct resource" do + a_get("/user").should have_been_made + end + + it "should return information about a current user" do + @user.email.should == "john@example.com" + end + end + end + + describe ".session" do + before do + stub_post("/session", "session") + @session = Gitlab.session("email", "pass") + end + + it "should get the correct resource" do + a_post("/session").should have_been_made + end + + it "should return information about a session" do + @session.email.should == "john@example.com" + @session.private_token.should == "qEsq1pt6HJPaNciie3MG" + end + end + + describe ".ssh_keys" do + before do + stub_get("/user/keys", "keys") + @keys = Gitlab.ssh_keys + end + + it "should get the correct resource" do + a_get("/user/keys").should have_been_made + end + + it "should return an array of SSH keys" do + @keys.should be_an Array + @keys.first.title.should == "narkoz@helium" + end + end + + describe ".ssh_key" do + before do + stub_get("/user/keys/1", "key") + @key = Gitlab.ssh_key(1) + end + + it "should get the correct resource" do + a_get("/user/keys/1").should have_been_made + end + + it "should return information about an SSH key" do + @key.title.should == "narkoz@helium" + end + end + + describe ".create_ssh_key" do + before do + stub_post("/user/keys", "key") + @key = Gitlab.create_ssh_key('title', 'body') + end + + it "should get the correct resource" do + body = {:title => 'title', :key => 'body'} + a_post("/user/keys").with(:body => body).should have_been_made + end + + it "should return information about a created SSH key" do + @key.title.should == "narkoz@helium" + end + end + + describe ".delete_ssh_key" do + before do + stub_delete("/user/keys/1", "key") + @key = Gitlab.delete_ssh_key(1) + end + + it "should get the correct resource" do + a_delete("/user/keys/1").should have_been_made + end + + it "should return information about a deleted SSH key" do + @key.title.should == "narkoz@helium" + end + end +end diff --git a/spec/gitlab_spec.rb b/spec/gitlab_spec.rb new file mode 100644 index 000000000..33f9786a8 --- /dev/null +++ b/spec/gitlab_spec.rb @@ -0,0 +1,62 @@ +require 'spec_helper' + +describe Gitlab do + after { Gitlab.reset } + + describe ".client" do + it "should be a Gitlab::Client" do + Gitlab.client.should be_a Gitlab::Client + end + end + + describe ".base_uri=" do + it "should set base_uri" do + Gitlab.base_uri = 'https://api.example.com' + Gitlab.base_uri.should == 'https://api.example.com' + end + end + + describe ".endpoint" do + it "should return default endpoint" do + Gitlab.endpoint.should == Gitlab::Configuration::DEFAULT_ENDPOINT + end + end + + describe ".endpoint=" do + it "should set endpoint" do + Gitlab.endpoint = nil + Gitlab.endpoint.should be_nil + end + end + + describe ".private_token=" do + it "should set private token" do + Gitlab.private_token = 'secret' + Gitlab.private_token.should == 'secret' + end + end + + describe ".user_agent" do + it "should return default user agent" do + Gitlab.user_agent.should == Gitlab::Configuration::DEFAULT_USER_AGENT + end + end + + describe ".user_agent=" do + it "should set user agent" do + Gitlab.user_agent = 'Custom User Agent' + Gitlab.user_agent.should == 'Custom User Agent' + end + end + + describe ".configure" do + Gitlab::Configuration::VALID_OPTIONS_KEYS.each do |key| + it "should set #{key}" do + Gitlab.configure do |config| + config.send("#{key}=", key) + Gitlab.send(key).should == key + end + end + end + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb new file mode 100644 index 000000000..79ceabdc8 --- /dev/null +++ b/spec/spec_helper.rb @@ -0,0 +1,64 @@ +require 'rspec' +require 'webmock/rspec' + +require File.expand_path('../../lib/gitlab', __FILE__) + +def load_fixture(name) + File.new(File.dirname(__FILE__) + "/fixtures/#{name}.json") +end + +RSpec.configure do |config| + config.before(:all) do + Gitlab.base_uri = 'https://api.example.com' + Gitlab.endpoint = nil + Gitlab.private_token = 'secret' + end +end + +# GET +def stub_get(path, fixture) + stub_request(:get, "#{Gitlab.base_uri}#{path}"). + with(:query => {:private_token => Gitlab.private_token}). + to_return(:body => load_fixture(fixture)) +end + +def a_get(path) + a_request(:get, "#{Gitlab.base_uri}#{path}"). + with(:query => {:private_token => Gitlab.private_token}) +end + +# POST +def stub_post(path, fixture) + stub_request(:post, "#{Gitlab.base_uri}#{path}"). + with(:query => {:private_token => Gitlab.private_token}). + to_return(:body => load_fixture(fixture)) +end + +def a_post(path) + a_request(:post, "#{Gitlab.base_uri}#{path}"). + with(:query => {:private_token => Gitlab.private_token}) +end + +# PUT +def stub_put(path, fixture) + stub_request(:put, "#{Gitlab.base_uri}#{path}"). + with(:query => {:private_token => Gitlab.private_token}). + to_return(:body => load_fixture(fixture)) +end + +def a_put(path) + a_request(:put, "#{Gitlab.base_uri}#{path}"). + with(:query => {:private_token => Gitlab.private_token}) +end + +# DELETE +def stub_delete(path, fixture) + stub_request(:delete, "#{Gitlab.base_uri}#{path}"). + with(:query => {:private_token => Gitlab.private_token}). + to_return(:body => load_fixture(fixture)) +end + +def a_delete(path) + a_request(:delete, "#{Gitlab.base_uri}#{path}"). + with(:query => {:private_token => Gitlab.private_token}) +end