diff --git a/Jenkinsfile b/Jenkinsfile index f14f88f..091d725 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -26,10 +26,10 @@ pipeline { stage('Run tests') { steps { catchError(buildResult: 'UNSTABLE', stageResult: 'FAILURE') { - sh 'cucumber features --format html --out coverage/cucumber.html' + sh 'cucumber features --format html --out cucumber.html' } catchError(buildResult: 'UNSTABLE', stageResult: 'FAILURE') { - sh 'rspec spec --format html --out coverage/spec.html' + sh 'rspec spec --format html --out spec.html' } } } @@ -40,8 +40,8 @@ pipeline { allowMissing: false, alwaysLinkToLastBuild: false, keepAll: true, - reportDir: 'coverage', - reportFiles: 'cucumber.html, spec.html, index.html', + reportDir: '.', + reportFiles: 'cucumber.html, spec.html, coverage/index.html', reportName: 'Test Results', reportTitles: 'Cucumber Results, RSpec Results, Test Coverage']) } diff --git a/app.rb b/app.rb index b8501a6..b9ef9e5 100644 --- a/app.rb +++ b/app.rb @@ -2,6 +2,7 @@ require 'roda' require 'securerandom' require 'json' require 'sequel' +require 'open-uri' class App < Roda plugin :sessions, secret: ENV.delete('APP_SESSION_SECRET') @@ -33,6 +34,20 @@ class App < Roda flash['message'] = "Please enter a valid URL"; r.redirect '/' end + + begin + OpenURI.open_uri(url) + rescue URI::BadURIError + flash['message'] = "Invalid URL" + r.redirect '/' + rescue OpenURI::HTTPError + flash['message'] = "URL not found" + r.redirect '/' + rescue SocketError => e + flash['message'] = "URL does not resolve" + r.redirect '/' + end + if links.filter(:url => url).first.nil? code = SecureRandom.urlsafe_base64 4 links.insert(url: url, code: code) @@ -46,7 +61,8 @@ class App < Roda r.on "links" do r.post do if 'application/json' != r.headers['CONTENT_TYPE'] - return {message: "Not a valid JSON request"}.to_json + response.status = 400 + return {message: "not a valid json request"}.to_json end url = r.params['url'] @@ -60,6 +76,19 @@ class App < Roda return {message: "invalid url parameter"}.to_json end + begin + OpenURI.open_uri(url) + rescue URI::BadURIError + response.status = 400 + return {message: "invalid url parameter"}.to_json + rescue OpenURI::HTTPError + response.status = 400 + return {message: "url not found"}.to_json + rescue SocketError => e + response.status = 400 + return {message: "url does not resolve"}.to_json + end + if links.filter(:url => url).first.nil? code = SecureRandom.urlsafe_base64 4 links.insert(url: url, code: code) diff --git a/features/step_definitions/steps.rb b/features/step_definitions/steps.rb index d1581a3..04262a8 100644 --- a/features/step_definitions/steps.rb +++ b/features/step_definitions/steps.rb @@ -63,7 +63,7 @@ Then('I should be redirected to {string}') do |string| end Then('The status code should be {int}') do |code| - puts page.status_code.should eq(code) + page.status_code.should eq(code) end diff --git a/features/submit.feature b/features/submit.feature index 422e082..7bbbf69 100644 --- a/features/submit.feature +++ b/features/submit.feature @@ -26,3 +26,27 @@ Feature: Submit And I click the "Submit" button Then I should be on "/create" page And I should see the message "Link exists" + + @db-test + Scenario: Submitting the form with a URL that is 404 + Given I visit the "/" page + When I type "http://google.com/example" in the "url" field + And I click the "Submit" button + Then I should be on "/" page + And I should see the message "URL not found" + + @db-test + Scenario: Submitting the form with a URL that does not resolve + Given I visit the "/" page + When I type "http://bad.tld" in the "url" field + And I click the "Submit" button + Then I should be on "/" page + And I should see the message "URL does not resolve" + + @db-test + Scenario: Submitting the form with an invalid URL + Given I visit the "/" page + When I type "not-an-url" in the "url" field + And I click the "Submit" button + Then I should be on "/" page + And I should see the message "Invalid URL" diff --git a/spec/create_spec.rb b/spec/create_spec.rb index c814803..4ef0610 100644 --- a/spec/create_spec.rb +++ b/spec/create_spec.rb @@ -1,3 +1,6 @@ +require 'simplecov' +SimpleCov.start + require_relative '../.env' ENV["DB_NAME"] = "test_#{ENV["DB_NAME"]}" require_relative '../app' @@ -45,8 +48,8 @@ describe "Submit API request to create new link" do expect(last_response.status).to eq(400) response_json = JSON.parse(last_response.body) expect(response_json['message']).to eq('invalid url parameter') - end + it "should return with a 400 status and 'missing url parameter' message when an empty url is submitted" do data = { } @@ -54,7 +57,45 @@ describe "Submit API request to create new link" do expect(last_response.status).to eq(400) response_json = JSON.parse(last_response.body) expect(response_json['message']).to eq('missing url parameter') + end + it "should return with a 400 status and 'invalid url parameter' message when an invalid url is submitted" do + data = { + url: 'not-an-url' + } + post('/links', data.to_json, "CONTENT_TYPE" => "application/json") + expect(last_response.status).to eq(400) + response_json = JSON.parse(last_response.body) + expect(response_json['message']).to eq('invalid url parameter') + end + + it "should return with a 400 status and 'url not found' message when a 404 url is submitted" do + data = { + url: 'http://google.com/example' + } + post('/links', data.to_json, "CONTENT_TYPE" => "application/json") + expect(last_response.status).to eq(400) + response_json = JSON.parse(last_response.body) + expect(response_json['message']).to eq('url not found') + end + + it "should return with a 400 status and 'url not found' message when a URL with no DNS is submitted" do + data = { + url: 'http://bad.tld' + } + post('/links', data.to_json, "CONTENT_TYPE" => "application/json") + expect(last_response.status).to eq(400) + response_json = JSON.parse(last_response.body) + expect(response_json['message']).to eq('url does not resolve') + end + + it "should return with a 400 status and 'not a valid json request' message when a request is made with the wrong content type header" do + data = { + url: 'http://google.com' + } + post('/links', data.to_json) + expect(last_response.status).to eq(400) + response_json = JSON.parse(last_response.body) + expect(response_json['message']).to eq('not a valid json request') end end -