diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 3bc29da..82e1780 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -5,4 +5,4 @@ # the repo. Unless a later match takes precedence, # @global-owner1 and @global-owner2 will be requested for # review when someone opens a pull request. -* @cdavis-personal +* @cdaviis @tpospisil diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 43e9e66..e181f57 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -5,4 +5,4 @@ Describe the change(s). Describe the reason for the change(s). ## Testing -Describe how to test your change(s). \ No newline at end of file +Describe how to test your change(s). diff --git a/.github/workflows/gem-push.yml b/.github/workflows/gem-push.yml index a9d9bdd..4e755a4 100644 --- a/.github/workflows/gem-push.yml +++ b/.github/workflows/gem-push.yml @@ -2,9 +2,9 @@ name: Ruby Gem on: push: - branches: [ "main" ] + # branches: [ "main" ] pull_request: - branches: [ "main" ] + # branches: [ "main" ] jobs: build: diff --git a/CHANGELOG.md b/CHANGELOG.md index f177e6a..7a665b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,27 @@ ## [Unreleased] +## [0.6.0] - 2025-08-20 + +### Changed +- Updated Test Cycles resource to support `testCycleIdOrKey` parameter for all relevant methods +- Renamed resource methods for consistency with the API (e.g., `create_test_cycle` instead of `create_testcycle`) +- Updated CLI implementation to handle both ID and key parameters +- Changed payload generators to use `projectKey` instead of `projectId` to match API requirements +- Improved CLI parameter handling using Thor options hash +- Added better handling for boolean parameters in automation payloads + +### Added +- Added aliases for backward compatibility with old method names +- Added better parameter descriptions in CLI commands +- Added support for `autoCloseCycle` parameter in automation payloads + +### Backward Compatibility +- Maintained full backward compatibility with existing code +- CLI commands support both positional arguments and options hash +- Payload generators accept both `project_id` (numeric) and `project_key` (string) +- Resource methods maintain aliases for old method names +- API client automatically handles both numeric IDs and string keys + ## [0.1.0] - 2022-11-24 - Initial release diff --git a/exe/zephyr b/exe/zephyr new file mode 100755 index 0000000..362ef35 --- /dev/null +++ b/exe/zephyr @@ -0,0 +1,7 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +require 'zephyr_ruby' +require 'zephyr_ruby/cli' + +ZephyrRuby::CLI::Main.start(ARGV) diff --git a/lib/zephyr_ruby.rb b/lib/zephyr_ruby.rb index 4d6ad5c..3830abc 100644 --- a/lib/zephyr_ruby.rb +++ b/lib/zephyr_ruby.rb @@ -5,4 +5,12 @@ module ZephyrRuby class Error < StandardError; end + + # Load CLI functionality if Thor is available + begin + require 'thor' + require_relative 'zephyr_ruby/cli' + rescue LoadError + # CLI functionality not available + end end diff --git a/lib/zephyr_ruby/cli.rb b/lib/zephyr_ruby/cli.rb new file mode 100644 index 0000000..891440d --- /dev/null +++ b/lib/zephyr_ruby/cli.rb @@ -0,0 +1,43 @@ +# frozen_string_literal: true + +require 'thor' +require 'nokogiri' +require_relative 'cli/helpers/cli_helpers' +require_relative 'cli/test_cycles' +require_relative 'cli/test_plans' + +module ZephyrRuby + module CLI + # Main CLI class for zephyr_ruby + class Main < Thor + class_option :api_key, type: :string, desc: 'Zephyr API Key (can also be set via ZEPHYR_API_KEY env var)' + + def initialize(*args) + super + # Only check for API key if we're not showing help + return if ARGV.include?('help') || ARGV.include?('--help') || ARGV.empty? + + api_key = options[:api_key] || ENV['ZEPHYR_API_KEY'] + unless api_key + puts "Error: API key is required. Set it with --api-key option or ZEPHYR_API_KEY env var" + exit(1) + end + + @zephyr_client = ZephyrRuby::Client.new(api_key) + end + + desc "test_cycles", "Test cycles commands" + subcommand "test_cycles", TestCycles + + desc "test_plans", "Test plans commands" + subcommand "test_plans", TestPlans + + # Make the client accessible to subcommands + no_commands do + def zephyr_client + @zephyr_client + end + end + end + end +end diff --git a/lib/zephyr_ruby/cli/helpers/cli_helpers.rb b/lib/zephyr_ruby/cli/helpers/cli_helpers.rb new file mode 100644 index 0000000..37a079e --- /dev/null +++ b/lib/zephyr_ruby/cli/helpers/cli_helpers.rb @@ -0,0 +1,77 @@ +# frozen_string_literal: true + +module ZephyrRuby + module CLI + # Helpers module to share common methods among the CLI classes + module Helpers + def generate_automations_payload(project_identifier, file, auto_close_cycle, name, description, auto_create_test_cases) + # Convert to boolean if it's not already + auto_create_test_cases = auto_create_test_cases.to_s.downcase == 'true' unless [true, false].include?(auto_create_test_cases) + + payload = { + file: file, + autoCreateTestCases: auto_create_test_cases, + testCycle: { + name: name, + description: description || "" + } + } + + # Handle different formats of project identifier for backward compatibility + if project_identifier.is_a?(Integer) || project_identifier.to_s.match?(/^\d+$/) + # Old style: numeric project_id - convert to string for new API + payload[:projectKey] = project_identifier.to_s + # Also include projectId for backward compatibility with any custom integrations + payload[:projectId] = project_identifier.to_i + else + # New style: string project_key + payload[:projectKey] = project_identifier + end + + # Add autoCloseCycle if provided + if auto_close_cycle + auto_close_cycle = auto_close_cycle.to_s.downcase == 'true' unless [true, false].include?(auto_close_cycle) + payload[:autoCloseCycle] = auto_close_cycle + end + + payload + end + + def generate_test_cycle_payload(name, description, start_date, end_date, project_identifier) + payload = { + name: name, + description: description, + plannedStartDate: start_date, + plannedEndDate: end_date + } + + # Handle different formats of project identifier for backward compatibility + if project_identifier.is_a?(Hash) + # New style: {key: value} format from refactored code + payload.merge!(project_identifier) + elsif project_identifier.is_a?(Integer) || project_identifier.to_s.match?(/^\d+$/) + # Old style: numeric project_id + payload[:projectId] = project_identifier.to_i + else + # New style: string project_key + payload[:projectKey] = project_identifier + end + + payload + end + + def generate_test_plan_payload(project_key, name, objective, folder_id, status_name, owner_id, labels, custom_fields = {}) + { + projectKey: project_key, + name: name, + objective: objective, + folderId: folder_id, + statusName: status_name, + ownerId: owner_id, + labels: labels, + customFields: custom_fields + } + end + end + end +end diff --git a/lib/zephyr_ruby/cli/test_cycles.rb b/lib/zephyr_ruby/cli/test_cycles.rb new file mode 100644 index 0000000..fb0ba82 --- /dev/null +++ b/lib/zephyr_ruby/cli/test_cycles.rb @@ -0,0 +1,260 @@ +# frozen_string_literal: true + +require 'thor' + +module ZephyrRuby + module CLI + # Subcommand for creating and updating test cycles as well as uploading results in junit and cucumber format + class TestCycles < Thor + include Helpers + + desc "upload_junit_results", "Upload test results in junit format" + method_option :project_key, type: :string, desc: "Project key (e.g. PROJ)" + method_option :project_id, type: :numeric, desc: "Project ID (numeric, deprecated but supported for backward compatibility)" + method_option :file, type: :string, desc: "Path to JUnit XML results file" + method_option :name, type: :string, desc: "Test cycle name" + method_option :description, type: :string, desc: "Test cycle description" + method_option :auto_create_test_cases, type: :boolean, desc: "Auto-create test cases if they don't exist" + method_option :auto_close_cycle, type: :boolean, desc: "Auto-close the test cycle after uploading" + def upload_junit_results(*args) + # Support both positional args and options hash for backward compatibility + if args.length >= 5 + # Old style: positional arguments + project_id_or_key, file, auto_close_cycle, name, description, auto_create_test_cases = args + + # Convert project_id to project_key if needed for API + project_key = project_id_or_key.is_a?(Integer) || project_id_or_key.to_s.match?(/^\d+$/) ? + project_id_or_key.to_s : project_id_or_key + else + # New style: options hash + # Priority: project_id (for backward compatibility) > project_key + project_key = options[:project_id] ? options[:project_id].to_s : options[:project_key] + raise "Either project_key or project_id must be provided" unless project_key + + file = options[:file] + raise "file is required" unless file + + name = options[:name] + raise "name is required" unless name + + description = options[:description] + auto_close_cycle = options[:auto_close_cycle] + auto_create_test_cases = options[:auto_create_test_cases] + end + + payload = generate_automations_payload( + project_key, + file, + auto_close_cycle, + name, + description, + auto_create_test_cases + ) + + parent_command.zephyr_client.create_automation_junit(payload) + end + + desc "upload_cucumber_results", "Upload test results in cucumber format" + method_option :project_key, type: :string, desc: "Project key (e.g. PROJ)" + method_option :project_id, type: :numeric, desc: "Project ID (numeric, deprecated but supported for backward compatibility)" + method_option :file, type: :string, desc: "Path to Cucumber JSON results file" + method_option :name, type: :string, desc: "Test cycle name" + method_option :description, type: :string, desc: "Test cycle description" + method_option :auto_create_test_cases, type: :boolean, desc: "Auto-create test cases if they don't exist" + method_option :auto_close_cycle, type: :boolean, desc: "Auto-close the test cycle after uploading" + def upload_cucumber_results(*args) + # Support both positional args and options hash for backward compatibility + if args.length >= 5 + # Old style: positional arguments + project_id_or_key, file, auto_close_cycle, name, description, auto_create_test_cases = args + + # Convert project_id to project_key if needed for API + project_key = project_id_or_key.is_a?(Integer) || project_id_or_key.to_s.match?(/^\d+$/) ? + project_id_or_key.to_s : project_id_or_key + else + # New style: options hash + # Priority: project_id (for backward compatibility) > project_key + project_key = options[:project_id] ? options[:project_id].to_s : options[:project_key] + raise "Either project_key or project_id must be provided" unless project_key + + file = options[:file] + raise "file is required" unless file + + name = options[:name] + raise "name is required" unless name + + description = options[:description] + auto_close_cycle = options[:auto_close_cycle] + auto_create_test_cases = options[:auto_create_test_cases] + end + + payload = generate_automations_payload( + project_key, + file, + auto_close_cycle, + name, + description, + auto_create_test_cases + ) + + parent_command.zephyr_client.create_automation_cucumber(payload) + end + + desc "create", "Create test cycle" + method_option :project_key, type: :string, desc: "Project key (e.g. PROJ)" + method_option :project_id, type: :numeric, desc: "Project ID (numeric, deprecated but supported for backward compatibility)" + method_option :name, type: :string, desc: "Test cycle name" + method_option :description, type: :string, desc: "Test cycle description" + method_option :start_date, type: :string, desc: "Planned start date (YYYY-MM-DD)" + method_option :end_date, type: :string, desc: "Planned end date (YYYY-MM-DD)" + def create(*args) + # Support both positional args and options hash for backward compatibility + if args.length >= 5 + # Old style: positional arguments + name, description, start_date, end_date, project_id_or_key = args + + # Convert project_id to project_key if needed + project_identifier = project_id_or_key.is_a?(Integer) || project_id_or_key.to_s.match?(/^\d+$/) ? + { projectId: project_id_or_key.to_i } : + { projectKey: project_id_or_key } + + payload = generate_test_cycle_payload(name, description, start_date, end_date, project_identifier.keys.first.to_s.sub('project', '') => project_identifier.values.first) + else + # New style: options hash + project_identifier = if options[:project_id] + { projectId: options[:project_id].to_i } + elsif options[:project_key] + { projectKey: options[:project_key] } + else + raise "Either project_key or project_id must be provided" + end + + payload = generate_test_cycle_payload( + options[:name], + options[:description], + options[:start_date], + options[:end_date], + project_identifier.keys.first.to_s.sub('project', '') => project_identifier.values.first + ) + end + + parent_command.zephyr_client.create_test_cycle(payload) + end + + desc "update", "Update test cycle" + method_option :test_cycle_id_or_key, type: :string, desc: "Test cycle ID or key (format: PROJECT-R123)" + method_option :name, type: :string, desc: "Test cycle name" + method_option :description, type: :string, desc: "Test cycle description" + method_option :start_date, type: :string, desc: "Planned start date (YYYY-MM-DD)" + method_option :end_date, type: :string, desc: "Planned end date (YYYY-MM-DD)" + method_option :project_key, type: :string, desc: "Project key (e.g. PROJ)" + method_option :project_id, type: :numeric, desc: "Project ID (numeric, deprecated but supported for backward compatibility)" + def update(*args) + # Support both positional args and options hash for backward compatibility + if args.length >= 6 + # Old style: positional arguments + test_cycle_id_or_key, name, description, start_date, end_date, project_id_or_key = args + + # Convert project_id to project_key if needed + project_identifier = project_id_or_key.is_a?(Integer) || project_id_or_key.to_s.match?(/^\d+$/) ? + { projectId: project_id_or_key.to_i } : + { projectKey: project_id_or_key } + + payload = generate_test_cycle_payload(name, description, start_date, end_date, project_identifier.keys.first.to_s.sub('project', '') => project_identifier.values.first) + else + # New style: options hash + raise "test_cycle_id_or_key is required" unless options[:test_cycle_id_or_key] + + project_identifier = if options[:project_id] + { projectId: options[:project_id].to_i } + elsif options[:project_key] + { projectKey: options[:project_key] } + else + raise "Either project_key or project_id must be provided" + end + + payload = generate_test_cycle_payload( + options[:name], + options[:description], + options[:start_date], + options[:end_date], + project_identifier.keys.first.to_s.sub('project', '') => project_identifier.values.first + ) + + test_cycle_id_or_key = options[:test_cycle_id_or_key] + end + + parent_command.zephyr_client.update_test_cycle(test_cycle_id_or_key, payload) + end + + desc "get", "Get test cycle details" + method_option :test_cycle_id_or_key, type: :string, desc: "Test cycle ID or key (format: PROJECT-R123)" + def get(*args) + # Support both positional args and options hash for backward compatibility + test_cycle_id_or_key = if args.length > 0 + # Old style: positional argument + args.first + else + # New style: options hash + raise "test_cycle_id_or_key is required" unless options[:test_cycle_id_or_key] + options[:test_cycle_id_or_key] + end + + parent_command.zephyr_client.get_test_cycle(test_cycle_id_or_key) + end + + desc "list", "List test cycles" + method_option :project_key, type: :string, required: false, desc: "Filter by project key" + method_option :project_id, type: :numeric, required: false, desc: "Filter by project ID (numeric, deprecated but supported for backward compatibility)" + method_option :max_results, type: :numeric, required: false, desc: "Maximum number of results to return" + def list(*args) + params = {} + + # Support both positional args and options hash for backward compatibility + if args.length > 0 + # Old style: positional arguments - project_id or project_key + project_id_or_key = args.first + + if project_id_or_key + if project_id_or_key.is_a?(Integer) || project_id_or_key.to_s.match?(/^\d+$/) + params[:projectId] = project_id_or_key.to_i + else + params[:projectKey] = project_id_or_key + end + end + + # Second arg could be max_results + params[:maxResults] = args[1].to_i if args.length > 1 && args[1] + else + # New style: options hash + # Priority: project_id (for backward compatibility) > project_key + if options[:project_id] + params[:projectId] = options[:project_id] + elsif options[:project_key] + params[:projectKey] = options[:project_key] + end + + params[:maxResults] = options[:max_results] if options[:max_results] + end + + parent_command.zephyr_client.list_test_cycles(params) + end + + desc "get_links", "Get test cycle links" + method_option :test_cycle_id_or_key, type: :string, desc: "Test cycle ID or key (format: PROJECT-R123)" + def get_links(*args) + # Support both positional args and options hash for backward compatibility + test_cycle_id_or_key = if args.length > 0 + # Old style: positional argument + args.first + else + # New style: options hash + raise "test_cycle_id_or_key is required" unless options[:test_cycle_id_or_key] + options[:test_cycle_id_or_key] + end + + parent_command.zephyr_client.get_test_cycle_links(test_cycle_id_or_key) + end + end + end +end diff --git a/lib/zephyr_ruby/cli/test_plans.rb b/lib/zephyr_ruby/cli/test_plans.rb new file mode 100644 index 0000000..dd17bc7 --- /dev/null +++ b/lib/zephyr_ruby/cli/test_plans.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +require 'thor' + +module ZephyrRuby + module CLI + # Subcommand for creating and updating test plans + class TestPlans < Thor + include Helpers + + desc "create", "Create test plan" + method_option :name, type: :string, required: true + method_option :project_id, type: :numeric, required: true + method_option :description, type: :string + method_option :objective, type: :string + method_option :folder_id, type: :string + method_option :status_name, type: :string + method_option :owner_id, type: :string + method_option :labels, type: :string + def create_test_plan(name, project_id, description, objective, folder_id, status_name, owner_id, labels) + testplan_payload = generate_test_plan_payload(project_id, name, objective, folder_id, status_name, owner_id, labels) + parent_command.zephyr_client.create_testplan(testplan_payload) + end + end + end +end diff --git a/lib/zephyr_ruby/resource/test_cycles.rb b/lib/zephyr_ruby/resource/test_cycles.rb index 516c5f9..dcbb03c 100644 --- a/lib/zephyr_ruby/resource/test_cycles.rb +++ b/lib/zephyr_ruby/resource/test_cycles.rb @@ -5,33 +5,58 @@ class Client module Resource # Operations related to Test Cycles module TestCycles - def create_testcycle(body) + # Create a new test cycle + def create_test_cycle(body) post '/testcycles', body end - def get_testcycle(testcycle_id) - get "/testcycles/#{testcycle_id}" + # Get a test cycle by ID or key + # @param test_cycle_id_or_key [String, Integer] The ID or key of the test cycle + def get_test_cycle(test_cycle_id_or_key) + get "/testcycles/#{test_cycle_id_or_key}" end - def update_testcycle(testcycle_id, params = {}) - put "/testcycles/#{testcycle_id}", params + # Update an existing test cycle + # @param test_cycle_id_or_key [String, Integer] The ID or key of the test cycle + # @param params [Hash] The parameters to update + def update_test_cycle(test_cycle_id_or_key, params = {}) + put "/testcycles/#{test_cycle_id_or_key}", params end - def list_testcycles(params = {}) + # List all test cycles with optional filtering + # @param params [Hash] Optional parameters for filtering + def list_test_cycles(params = {}) get '/testcycles', params end - def get_testcycle_links(testcycle_id) - get "/testcycles/#{testcycle_id}/links" + # Get links for a test cycle + # @param test_cycle_id_or_key [String, Integer] The ID or key of the test cycle + def get_test_cycle_links(test_cycle_id_or_key) + get "/testcycles/#{test_cycle_id_or_key}/links" end - def create_testcycle_issue_link(testcycle_id, body) - post "/testcycles/#{testcycle_id}/links/issues", body + # Create a link between a test cycle and a Jira issue + # @param test_cycle_id_or_key [String, Integer] The ID or key of the test cycle + # @param body [Hash] The issue link details + def create_test_cycle_issue_link(test_cycle_id_or_key, body) + post "/testcycles/#{test_cycle_id_or_key}/links/issues", body end - def create_testcycle_web_link(testcycle_id, body) - post "/testcycles/#{testcycle_id}/links/weblinks", body + # Create a link between a test cycle and a generic URL + # @param test_cycle_id_or_key [String, Integer] The ID or key of the test cycle + # @param body [Hash] The web link details + def create_test_cycle_web_link(test_cycle_id_or_key, body) + post "/testcycles/#{test_cycle_id_or_key}/links/weblinks", body end + + # Maintain backward compatibility with old method names + alias create_testcycle create_test_cycle + alias get_testcycle get_test_cycle + alias update_testcycle update_test_cycle + alias list_testcycles list_test_cycles + alias get_testcycle_links get_test_cycle_links + alias create_testcycle_issue_link create_test_cycle_issue_link + alias create_testcycle_web_link create_test_cycle_web_link end end end diff --git a/lib/zephyr_ruby/version.rb b/lib/zephyr_ruby/version.rb index d01f517..c639141 100644 --- a/lib/zephyr_ruby/version.rb +++ b/lib/zephyr_ruby/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module ZephyrRuby - VERSION = '0.5.0' + VERSION = '0.6.0' end diff --git a/test_api.rb b/test_api.rb new file mode 100755 index 0000000..a82823a --- /dev/null +++ b/test_api.rb @@ -0,0 +1,91 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +require 'bundler/setup' +require 'zephyr_ruby' +require 'json' + +# This script tests the updated Zephyr Ruby gem functionality +# Replace these values with your actual API credentials and project information +API_KEY = ENV['ZEPHYR_API_KEY'] || 'your_api_key_here' +PROJECT_KEY = 'TEST' # Replace with your project key + +# Initialize the client +client = ZephyrRuby::Client.new(api_key: API_KEY) + +# Test 1: Create a test cycle with project key +puts "=== Test 1: Creating a test cycle ===" +test_cycle_payload = { + name: "Test Cycle #{Time.now.to_i}", + description: "Test cycle created by API test script", + plannedStartDate: Date.today.to_s, + plannedEndDate: (Date.today + 7).to_s, + projectKey: PROJECT_KEY +} + +begin + response = client.create_test_cycle(test_cycle_payload) + puts "Success! Test cycle created:" + puts JSON.pretty_generate(response) + test_cycle_key = response['key'] + puts "Test cycle key: #{test_cycle_key}" +rescue => e + puts "Error creating test cycle: #{e.message}" +end + +# Test 2: Get test cycle by key +if defined?(test_cycle_key) + puts "\n=== Test 2: Getting test cycle by key ===" + begin + response = client.get_test_cycle(test_cycle_key) + puts "Success! Test cycle retrieved:" + puts JSON.pretty_generate(response) + rescue => e + puts "Error getting test cycle: #{e.message}" + end +end + +# Test 3: Update test cycle by key +if defined?(test_cycle_key) + puts "\n=== Test 3: Updating test cycle by key ===" + update_payload = { + name: "Updated Test Cycle #{Time.now.to_i}", + description: "Updated test cycle description", + plannedStartDate: Date.today.to_s, + plannedEndDate: (Date.today + 14).to_s, + projectKey: PROJECT_KEY + } + + begin + response = client.update_test_cycle(test_cycle_key, update_payload) + puts "Success! Test cycle updated:" + puts JSON.pretty_generate(response) + rescue => e + puts "Error updating test cycle: #{e.message}" + end +end + +# Test 4: List test cycles +puts "\n=== Test 4: Listing test cycles ===" +begin + params = { projectKey: PROJECT_KEY, maxResults: 5 } + response = client.list_test_cycles(params) + puts "Success! Test cycles listed:" + puts JSON.pretty_generate(response) +rescue => e + puts "Error listing test cycles: #{e.message}" +end + +# Test 5: Get test cycle links +if defined?(test_cycle_key) + puts "\n=== Test 5: Getting test cycle links ===" + begin + response = client.get_test_cycle_links(test_cycle_key) + puts "Success! Test cycle links retrieved:" + puts JSON.pretty_generate(response) + rescue => e + puts "Error getting test cycle links: #{e.message}" + end +end + +puts "\nAll tests completed!" diff --git a/test_backward_compatibility.rb b/test_backward_compatibility.rb new file mode 100644 index 0000000..a4cf7c2 --- /dev/null +++ b/test_backward_compatibility.rb @@ -0,0 +1,126 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +require 'bundler/setup' +require 'zephyr_ruby' +require 'json' + +# This script tests backward compatibility of the Zephyr Ruby gem +# Replace these values with your actual API credentials and project information +API_KEY = ENV['ZEPHYR_API_KEY'] || 'your_api_key_here' +PROJECT_ID = 12345 # Replace with a numeric project ID +PROJECT_KEY = 'TEST' # Replace with your project key +TEST_CYCLE_ID = 67890 # Replace with a numeric test cycle ID +TEST_CYCLE_KEY = 'TEST-R123' # Replace with a test cycle key + +# Initialize the client +client = ZephyrRuby::Client.new(api_key: API_KEY) + +puts "=== Testing Backward Compatibility ===" + +# Test 1: Using old method names (aliases) +puts "\n=== Test 1: Using old method names (aliases) ===" +begin + puts "Calling create_testcycle (old name)..." + test_cycle_payload = { + name: "Test Cycle Old Method #{Time.now.to_i}", + description: "Testing backward compatibility with old method names", + plannedStartDate: Date.today.to_s, + plannedEndDate: (Date.today + 7).to_s, + projectKey: PROJECT_KEY + } + response = client.create_testcycle(test_cycle_payload) + puts "Success! Test cycle created with old method name." + puts "Response contains key: #{response['key'] ? 'Yes' : 'No'}" +rescue => e + puts "Error using old method name: #{e.message}" +end + +# Test 2: Using numeric project_id instead of project_key +puts "\n=== Test 2: Using numeric project_id instead of project_key ===" +begin + puts "Creating test cycle with numeric project_id..." + test_cycle_payload = { + name: "Test Cycle Project ID #{Time.now.to_i}", + description: "Testing backward compatibility with numeric project ID", + plannedStartDate: Date.today.to_s, + plannedEndDate: (Date.today + 7).to_s, + projectId: PROJECT_ID + } + response = client.create_test_cycle(test_cycle_payload) + puts "Success! Test cycle created with numeric project ID." + puts "Response contains key: #{response['key'] ? 'Yes' : 'No'}" +rescue => e + puts "Error using numeric project ID: #{e.message}" +end + +# Test 3: Using numeric test_cycle_id instead of test_cycle_key +puts "\n=== Test 3: Using numeric test_cycle_id instead of test_cycle_key ===" +begin + puts "Getting test cycle with numeric ID..." + response = client.get_test_cycle(TEST_CYCLE_ID) + puts "Success! Got test cycle with numeric ID." + puts "Response contains name: #{response['name'] ? 'Yes' : 'No'}" +rescue => e + puts "Error using numeric test cycle ID: #{e.message}" +end + +# Test 4: Using string test_cycle_key +puts "\n=== Test 4: Using string test_cycle_key ===" +begin + puts "Getting test cycle with string key..." + response = client.get_test_cycle(TEST_CYCLE_KEY) + puts "Success! Got test cycle with string key." + puts "Response contains name: #{response['name'] ? 'Yes' : 'No'}" +rescue => e + puts "Error using string test cycle key: #{e.message}" +end + +# Test 5: CLI with positional arguments (using CLI class directly for testing) +puts "\n=== Test 5: CLI with positional arguments ===" +begin + require 'zephyr_ruby/cli/test_cycles' + + # Mock parent command with zephyr_client + class MockParent + attr_reader :zephyr_client + + def initialize(client) + @zephyr_client = client + end + end + + # Create a CLI instance with our client + cli = ZephyrRuby::CLI::TestCycles.new + cli.define_singleton_method(:parent_command) { MockParent.new(client) } + + # Test create with positional arguments + puts "Testing CLI create with positional arguments..." + name = "CLI Test Cycle #{Time.now.to_i}" + description = "Testing CLI backward compatibility" + start_date = Date.today.to_s + end_date = (Date.today + 7).to_s + + # Call with positional arguments (old style) + result = cli.create(name, description, start_date, end_date, PROJECT_ID) + puts "Success! CLI create with positional arguments works." + puts "Response contains key: #{result['key'] ? 'Yes' : 'No'}" + + # Test get with positional arguments + puts "Testing CLI get with positional arguments..." + test_cycle_id = result['id'] + result = cli.get(test_cycle_id) + puts "Success! CLI get with positional arguments works." + puts "Response contains name: #{result['name'] ? 'Yes' : 'No'}" + + # Test list with positional arguments + puts "Testing CLI list with positional arguments..." + result = cli.list(PROJECT_KEY, 10) + puts "Success! CLI list with positional arguments works." + puts "Response contains test cycles: #{result['values'] && !result['values'].empty? ? 'Yes' : 'No'}" +rescue => e + puts "Error testing CLI with positional arguments: #{e.message}" + puts e.backtrace.join("\n") +end + +puts "\nAll backward compatibility tests completed!" diff --git a/zephyr_ruby-0.5.0.gem b/zephyr_ruby-0.5.0.gem deleted file mode 100644 index 4531835..0000000 Binary files a/zephyr_ruby-0.5.0.gem and /dev/null differ diff --git a/zephyr_ruby-0.6.0.gem b/zephyr_ruby-0.6.0.gem new file mode 100644 index 0000000..0e7f850 Binary files /dev/null and b/zephyr_ruby-0.6.0.gem differ diff --git a/zephyr_ruby.gemspec b/zephyr_ruby.gemspec index b1c4882..96d1646 100644 --- a/zephyr_ruby.gemspec +++ b/zephyr_ruby.gemspec @@ -7,15 +7,17 @@ Gem::Specification.new do |spec| spec.version = ZephyrRuby::VERSION spec.authors = ['Chris Davis'] - spec.summary = 'Zephyr REST API Client for Ruby' - spec.description = "Allows users to use Zephyr's REST API" + spec.summary = 'Zephyr REST API Client and CLI for Ruby' + spec.description = "Allows users to use Zephyr's REST API and provides a command-line interface" spec.license = 'MIT' spec.required_ruby_version = '>= 3.0' spec.homepage = 'https://github.com/cdavis-personal/zephyr_ruby' spec.files = Dir.chdir(__dir__) do `git ls-files -z`.split("\x0").reject do |f| - (f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|travis|circleci)|appveyor)}) + (f == __FILE__) || + f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|travis|circleci)|appveyor)}) || + f.end_with?(".gem") end end spec.bindir = 'exe' @@ -25,4 +27,6 @@ Gem::Specification.new do |spec| spec.add_dependency 'faraday', '~> 1.7', '>= 1.7.0' spec.add_dependency 'json', '~> 2.3', '>= 2.3.0' spec.add_dependency 'rspec', '~> 3.7', '>= 3.7.0' + spec.add_dependency 'thor', '~> 1.0' + spec.add_dependency 'nokogiri', '~> 1.12' end