diff --git a/spec/basic_behavior_spec.rb b/spec/basic_behavior_spec.rb index cca62d7..f2e173e 100644 --- a/spec/basic_behavior_spec.rb +++ b/spec/basic_behavior_spec.rb @@ -20,8 +20,7 @@ } ) - jobs = ctx.kombo.ats.get_jobs - jobs.each { |_page| break } + ctx.kombo.ats.get_jobs request = ctx.get_last_request expect(request.headers['Authorization']).to eq('Bearer my-custom-api-key') @@ -44,8 +43,7 @@ } ) - jobs = ctx.kombo.ats.get_jobs - jobs.each { |_page| break } + ctx.kombo.ats.get_jobs request = ctx.get_last_request expect(request.headers['X-Integration-Id']).to eq('my-integration-123') @@ -68,8 +66,7 @@ } ) - jobs = ctx.kombo.ats.get_jobs - jobs.each { |_page| break } + ctx.kombo.ats.get_jobs request = ctx.get_last_request # When integration ID is undefined, the header is not set @@ -125,8 +122,7 @@ ) # Test with boolean true - jobs_with_deleted = ctx.kombo.ats.get_jobs(include_deleted: true) - jobs_with_deleted.each { |_page| break } + ctx.kombo.ats.get_jobs(include_deleted: true) request_with_deleted = ctx.get_last_request expect(request_with_deleted.path).to include('include_deleted=true') @@ -145,8 +141,7 @@ ) # Test with boolean false - jobs_without_deleted = ctx.kombo.ats.get_jobs(include_deleted: false) - jobs_without_deleted.each { |_page| break } + ctx.kombo.ats.get_jobs(include_deleted: false) request_without_deleted = ctx.get_last_request expect(request_without_deleted.path).to include('include_deleted=false') @@ -530,4 +525,3 @@ end end end - diff --git a/spec/employee_form_flow_spec.rb b/spec/employee_form_flow_spec.rb index d4c9df2..5fb6070 100644 --- a/spec/employee_form_flow_spec.rb +++ b/spec/employee_form_flow_spec.rb @@ -163,7 +163,7 @@ # Verify request body is correctly serialized request = ctx.get_last_request - expect(request.method).to eq('POST') + expect(request.http_method).to eq('POST') expect(request.body).to be_a(Hash) expect(request.body['properties']).to be_truthy expect(request.body['properties']['firstName']).to eq('John') @@ -174,4 +174,3 @@ expect(request.body['properties']['workLocation']['site']).to eq('FXrER44xubBqA9DLgZ3PFNNx') end end - diff --git a/spec/error_handling_spec.rb b/spec/error_handling_spec.rb index c99a43a..e4050ca 100644 --- a/spec/error_handling_spec.rb +++ b/spec/error_handling_spec.rb @@ -27,17 +27,19 @@ } ) + error = nil expect do - jobs = ctx.kombo.ats.get_jobs - jobs.each { |_page| break } - end.to raise_error(Kombo::Models::Errors::KomboAtsError) do |error| - expect(error.error.message).to include('You have exceeded the rate limit. Please try again later.') - expect(error.status).to eq(Kombo::Models::Shared::KomboAtsErrorStatus::ERROR) - expect(error.error.code).to eq(Kombo::Models::Shared::KomboAtsErrorCode::PLATFORM_RATE_LIMIT_EXCEEDED) - expect(error.error.title).to eq('Rate limit exceeded') - expect(error.error.message).to eq('You have exceeded the rate limit. Please try again later.') - expect(error.error.log_url).to eq('https://app.kombo.dev/logs/abc123') - end + ctx.kombo.ats.get_jobs + rescue Kombo::Models::Errors::KomboAtsError => e + error = e + raise + end.to raise_error(Kombo::Models::Errors::KomboAtsError) + expect(error.error.message).to include('You have exceeded the rate limit. Please try again later.') + expect(error.status).to eq(Kombo::Models::Shared::KomboAtsErrorStatus::ERROR) + expect(error.error.code).to eq(Kombo::Models::Shared::KomboAtsErrorCode::PLATFORM_RATE_LIMIT_EXCEEDED) + expect(error.error.title).to eq('Rate limit exceeded') + expect(error.error.message).to eq('You have exceeded the rate limit. Please try again later.') + expect(error.error.log_url).to eq('https://app.kombo.dev/logs/abc123') end it 'returns KomboAtsError for ATS-specific job closed errors' do @@ -69,16 +71,19 @@ candidate: candidate ) + error = nil expect do ctx.kombo.ats.create_application(job_id: 'test-job-id', body: body) - end.to raise_error(Kombo::Models::Errors::KomboAtsError) do |error| - expect(error.error.message).to include('Cannot create application for a closed job. The job must be in an open state.') - expect(error.status).to eq(Kombo::Models::Shared::KomboAtsErrorStatus::ERROR) - expect(error.error.code).to eq(Kombo::Models::Shared::KomboAtsErrorCode::ATS_JOB_CLOSED) - expect(error.error.title).to eq('Job is closed') - expect(error.error.message).to eq('Cannot create application for a closed job. The job must be in an open state.') - expect(error.error.log_url).to eq('https://app.kombo.dev/logs/ghi789') - end + rescue Kombo::Models::Errors::KomboAtsError => e + error = e + raise + end.to raise_error(Kombo::Models::Errors::KomboAtsError) + expect(error.error.message).to include('Cannot create application for a closed job. The job must be in an open state.') + expect(error.status).to eq(Kombo::Models::Shared::KomboAtsErrorStatus::ERROR) + expect(error.error.code).to eq(Kombo::Models::Shared::KomboAtsErrorCode::ATS_JOB_CLOSED) + expect(error.error.title).to eq('Job is closed') + expect(error.error.message).to eq('Cannot create application for a closed job. The job must be in an open state.') + expect(error.error.log_url).to eq('https://app.kombo.dev/logs/ghi789') end end @@ -103,17 +108,19 @@ } ) + error = nil expect do - employees = ctx.kombo.hris.get_employees - employees.each { |_page| break } - end.to raise_error(Kombo::Models::Errors::KomboHrisError) do |error| - expect(error.error.message).to include('The integration is missing required permissions to access this resource.') - expect(error.status).to eq(Kombo::Models::Shared::KomboHrisErrorStatus::ERROR) - expect(error.error.code).to eq(Kombo::Models::Shared::KomboHrisErrorCode::INTEGRATION_PERMISSION_MISSING) - expect(error.error.title).to eq('Permission missing') - expect(error.error.message).to eq('The integration is missing required permissions to access this resource.') - expect(error.error.log_url).to eq('https://app.kombo.dev/logs/hris-def456') - end + ctx.kombo.hris.get_employees + rescue Kombo::Models::Errors::KomboHrisError => e + error = e + raise + end.to raise_error(Kombo::Models::Errors::KomboHrisError) + expect(error.error.message).to include('The integration is missing required permissions to access this resource.') + expect(error.status).to eq(Kombo::Models::Shared::KomboHrisErrorStatus::ERROR) + expect(error.error.code).to eq(Kombo::Models::Shared::KomboHrisErrorCode::INTEGRATION_PERMISSION_MISSING) + expect(error.error.title).to eq('Permission missing') + expect(error.error.message).to eq('The integration is missing required permissions to access this resource.') + expect(error.error.log_url).to eq('https://app.kombo.dev/logs/hris-def456') end end @@ -138,17 +145,19 @@ } ) + error = nil expect do - orders = ctx.kombo.assessment.get_open_orders - orders.each { |_page| break } - end.to raise_error(Kombo::Models::Errors::KomboAtsError) do |error| - expect(error.error.message).to include('The provided input is invalid or malformed.') - expect(error.status).to eq(Kombo::Models::Shared::KomboAtsErrorStatus::ERROR) - expect(error.error.code).to eq(Kombo::Models::Shared::KomboAtsErrorCode::PLATFORM_INPUT_INVALID) - expect(error.error.title).to eq('Input invalid') - expect(error.error.message).to eq('The provided input is invalid or malformed.') - expect(error.error.log_url).to eq('https://app.kombo.dev/logs/assessment-xyz') - end + ctx.kombo.assessment.get_open_orders + rescue Kombo::Models::Errors::KomboAtsError => e + error = e + raise + end.to raise_error(Kombo::Models::Errors::KomboAtsError) + expect(error.error.message).to include('The provided input is invalid or malformed.') + expect(error.status).to eq(Kombo::Models::Shared::KomboAtsErrorStatus::ERROR) + expect(error.error.code).to eq(Kombo::Models::Shared::KomboAtsErrorCode::PLATFORM_INPUT_INVALID) + expect(error.error.title).to eq('Input invalid') + expect(error.error.message).to eq('The provided input is invalid or malformed.') + expect(error.error.log_url).to eq('https://app.kombo.dev/logs/assessment-xyz') end end @@ -173,16 +182,19 @@ } ) + error = nil expect do ctx.kombo.general.check_api_key - end.to raise_error(Kombo::Models::Errors::KomboGeneralError) do |error| - expect(error.error.message).to include('The provided API key is invalid or expired.') - expect(error.status).to eq(Kombo::Models::Shared::KomboGeneralErrorStatus::ERROR) - expect(error.error.code).to eq(Kombo::Models::Shared::KomboGeneralErrorCode::PLATFORM_AUTHENTICATION_INVALID) - expect(error.error.title).to eq('Authentication invalid') - expect(error.error.message).to eq('The provided API key is invalid or expired.') - expect(error.error.log_url).to eq('https://app.kombo.dev/logs/general-auth-123') - end + rescue Kombo::Models::Errors::KomboGeneralError => e + error = e + raise + end.to raise_error(Kombo::Models::Errors::KomboGeneralError) + expect(error.error.message).to include('The provided API key is invalid or expired.') + expect(error.status).to eq(Kombo::Models::Shared::KomboGeneralErrorStatus::ERROR) + expect(error.error.code).to eq(Kombo::Models::Shared::KomboGeneralErrorCode::PLATFORM_AUTHENTICATION_INVALID) + expect(error.error.title).to eq('Authentication invalid') + expect(error.error.message).to eq('The provided API key is invalid or expired.') + expect(error.error.log_url).to eq('https://app.kombo.dev/logs/general-auth-123') end end @@ -201,13 +213,15 @@ } ) + error = nil expect do - jobs = ctx.kombo.ats.get_jobs - jobs.each { |_page| break } - end.to raise_error(Kombo::Models::Errors::APIError) do |error| - expect(error.status_code).to eq(500) - expect(error.body).to include('500 Internal Server Error') - end + ctx.kombo.ats.get_jobs + rescue Kombo::Models::Errors::APIError => e + error = e + raise + end.to raise_error(Kombo::Models::Errors::APIError) + expect(error.status_code).to eq(500) + expect(error.body).to include('500 Internal Server Error') end it 'handles plain text 502 bad gateway error' do @@ -225,13 +239,15 @@ } ) + error = nil expect do - employees = ctx.kombo.hris.get_employees - employees.each { |_page| break } - end.to raise_error(Kombo::Models::Errors::APIError) do |error| - expect(error.status_code).to eq(502) - expect(error.body).to include('502 Bad Gateway') - end + ctx.kombo.hris.get_employees + rescue Kombo::Models::Errors::APIError => e + error = e + raise + end.to raise_error(Kombo::Models::Errors::APIError) + expect(error.status_code).to eq(502) + expect(error.body).to include('502 Bad Gateway') end it 'handles HTML error page from nginx' do @@ -267,12 +283,15 @@ candidate: candidate ) + error = nil expect do ctx.kombo.ats.create_application(job_id: 'test-job-id', body: body) - end.to raise_error(Kombo::Models::Errors::APIError) do |error| - expect(error.status_code).to eq(503) - expect(error.body).to include('503 Service Temporarily Unavailable') - end + rescue Kombo::Models::Errors::APIError => e + error = e + raise + end.to raise_error(Kombo::Models::Errors::APIError) + expect(error.status_code).to eq(503) + expect(error.body).to include('503 Service Temporarily Unavailable') end it 'handles empty response body with error status code' do @@ -288,11 +307,14 @@ } ) + error = nil expect do ctx.kombo.general.check_api_key - end.to raise_error(Kombo::Models::Errors::APIError) do |error| - expect(error.status_code).to eq(500) - end + rescue Kombo::Models::Errors::APIError => e + error = e + raise + end.to raise_error(Kombo::Models::Errors::APIError) + expect(error.status_code).to eq(500) end it 'handles unexpected Content-Type header' do @@ -311,15 +333,16 @@ } ) + error = nil expect do - applications = ctx.kombo.ats.get_applications - applications.each { |_page| break } - end.to raise_error(Kombo::Models::Errors::APIError) do |error| - expect(error.status_code).to eq(500) - expect(error.body).to include('Server error occurred') - end + ctx.kombo.ats.get_applications + rescue Kombo::Models::Errors::APIError => e + error = e + raise + end.to raise_error(Kombo::Models::Errors::APIError) + expect(error.status_code).to eq(500) + expect(error.body).to include('Server error occurred') end end end end - diff --git a/spec/job_board_spec.rb b/spec/job_board_spec.rb index c873e42..80c0cd2 100644 --- a/spec/job_board_spec.rb +++ b/spec/job_board_spec.rb @@ -31,8 +31,7 @@ request = ctx.get_last_request # The path should include the base path expect(request.path).to include('/v1/ats/jobs') - # Note: Default query parameters may or may not be included in the URL + # NOTE: Default query parameters may or may not be included in the URL # depending on how the query parameter serialization handles default values end end - diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index dd6bbbb..70ab82e 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -28,4 +28,3 @@ WebMock.allow_net_connect! end end - diff --git a/spec/support/test_context.rb b/spec/support/test_context.rb index 92d7142..0a3f7d3 100644 --- a/spec/support/test_context.rb +++ b/spec/support/test_context.rb @@ -5,7 +5,7 @@ require 'kombo' module TestSupport - CapturedRequest = Struct.new(:method, :path, :headers, :body, keyword_init: true) + CapturedRequest = Struct.new(:http_method, :path, :headers, :body, keyword_init: true) class TestContext attr_reader :kombo @@ -50,14 +50,14 @@ def initialize(api_key: 'test-api-key', integration_id: 'test-integration-id') uri_str = uri.to_s path_start = uri_str.index(uri.path) if path_start - full_path = uri_str[path_start..-1] + full_path = uri_str[path_start..] # Remove fragment if present full_path = full_path.split('#').first end end captured = CapturedRequest.new( - method: request_signature.method.to_s.upcase, + http_method: request_signature.method.to_s.upcase, path: full_path, headers: headers_hash, body: body @@ -83,18 +83,18 @@ def mock_endpoint(method:, path:, response:) # will be matched sequentially. Use times(1) to ensure each stub only matches once. url_pattern = if method == 'GET' # Use regex to match path with any query params - /^https:\/\/api\.kombo\.dev#{Regexp.escape(path)}(\?.*)?$/ + %r{^https://api\.kombo\.dev#{Regexp.escape(path)}(\?.*)?$} else "https://api.kombo.dev#{path}" end stub = WebMock.stub_request(method.downcase.to_sym, url_pattern) - .to_return( - status: status_code, - body: body.to_json, - headers: headers - ) - .times(1) + .to_return( + status: status_code, + body: body.to_json, + headers: headers + ) + .times(1) @stubs << stub end @@ -138,4 +138,3 @@ def self.describe_sdk_suite(name, &block) end end end -