Compare commits

..

30 Commits

Author SHA1 Message Date
bucky 5631ae386f include rackup 2023-10-13 21:28:47 -07:00
bucky c31c556df5 removed falcon and it's dependencies, because it wasn't working right.
use puma for now
2023-10-13 21:27:25 -07:00
bucky 5fae0c4fa9 Merge pull request 'rspec-coverage' (#22) from rspec-coverage into master
Reviewed-on: #22
2023-10-12 23:49:48 -07:00
bucky 144731062b added URL validation to webpage part 2023-10-12 23:42:52 -07:00
bucky 72f3e03edd added tests for invalid URL entries
+ URL that returns a 404
+ URL where the domain does not resolve with DNS
+ URL that is not properly formatted
2023-10-12 23:42:04 -07:00
bucky b08693e866 remove the puts, don't print out the test result 2023-10-12 23:41:38 -07:00
bucky ae2360a480 include the proper status code 2023-10-12 23:31:15 -07:00
bucky 213265a5d0 added test for submitting with the wrong content type header 2023-10-12 23:30:47 -07:00
bucky dfb6b23e70 run simplecov for rspec tests 2023-10-12 23:12:14 -07:00
bucky c81a7a6160 added rescue for urls that don't resolve 2023-10-12 19:03:03 -07:00
bucky bbb710a5e1 added test for bad TLD, better named 404 url test 2023-10-12 19:02:38 -07:00
bucky 7eaa8eacf8 added rescue for OpenURI HTTPErrors 2023-10-12 18:26:13 -07:00
bucky d78e361c29 added test for validating a url is accessible 2023-10-12 18:25:38 -07:00
bucky 1ae6c02472 rescue BadURIError for invalid URL format 2023-10-12 18:20:56 -07:00
bucky 11206854ad added test for an invalid url 2023-10-12 18:20:35 -07:00
bucky 33089e6fbd build HTML output with cucumber and rspec files in root dir 2023-10-12 16:25:22 -07:00
bucky 5cec47efcc Merge pull request 'create-json' (#21) from create-json into master
Reviewed-on: #21
2023-10-12 14:36:38 -07:00
bucky cabb4daded split up the nil? and empty? cases, because they are different
situations
2023-10-12 14:27:31 -07:00
bucky 1e61a76ded added 2 more tests for empty and missing url data posting to links 2023-10-12 14:27:02 -07:00
bucky ac3e9f14cd added links route for API interactions 2023-10-12 11:42:43 -07:00
bucky 5ee9351362 added db initialization to make sure the db exists and is up to date
before tests
2023-10-12 11:42:14 -07:00
bucky 2964e06639 added before and after actions
+ before initializes the db
+ after cleans the db
2023-10-12 11:40:15 -07:00
bucky d1a0fc0222 change request to use the /links path, to fit more into a RESTful API
format

+ also renamed the test to better describe the behavior
2023-10-12 11:32:00 -07:00
bucky 4a82174526 implemented API create endpoint
+ added plugins to read json and access the header to parse the request
  for an API request
+ fixed logic where url param is nil
+ refactored the new code to a variable to be reused easier
+ if CONTENT_TYPE header is application/json, reply with json
- there could be more refactoring (maybe separating it to a different
  endpoint) to handle other scenarios, we'll work on that later
2023-10-11 19:21:43 -07:00
bucky 3ae20255f6 DRY it out a little 2023-10-11 19:21:21 -07:00
bucky f69c53bf29 removed unnecessary variable 2023-10-11 19:20:07 -07:00
bucky 7d6c098047 added more to the spec test for creating a new link 2023-10-11 19:18:47 -07:00
bucky 3421e18f21 added more logic for running tests without killing the whole pipeline, and outputting rspec results 2023-10-11 12:05:33 -07:00
bucky 0dec27a01c added rspec step in tests stage, adjusted should clause 2023-10-11 11:04:08 -07:00
bucky c45cf6ab51 started building out rspec specs for API functionality 2023-10-11 11:01:46 -07:00
7 changed files with 209 additions and 72 deletions
+4 -1
View File
@@ -2,7 +2,6 @@
source "https://rubygems.org"
gem "falcon", "~> 0.42.3"
gem "roda", "~> 3.72"
@@ -27,3 +26,7 @@ group :test do
gem "simplecov"
end
gem "puma", "~> 6.4"
gem "rackup", "~> 2.1"
+9 -64
View File
@@ -3,30 +3,7 @@ GEM
specs:
addressable (2.8.5)
public_suffix (>= 2.0.2, < 6.0)
async (2.6.4)
console (~> 1.10)
fiber-annotation
io-event (~> 1.1)
timers (~> 4.1)
async-container (0.16.12)
async
async-io
async-http (0.60.2)
async (>= 1.25)
async-io (>= 1.28)
async-pool (>= 0.2)
protocol-http (~> 0.24.0)
protocol-http1 (~> 0.15.0)
protocol-http2 (~> 0.15.0)
traces (>= 0.10.0)
async-http-cache (0.4.3)
async-http (~> 0.56)
async-io (1.36.0)
async
async-pool (0.4.0)
async (>= 1.25)
bigdecimal (3.1.4)
build-environment (1.13.0)
builder (3.2.4)
capybara (3.39.2)
addressable
@@ -37,9 +14,6 @@ GEM
rack-test (>= 0.6.3)
regexp_parser (>= 1.5, < 3.0)
xpath (~> 3.2)
console (1.23.2)
fiber-annotation
fiber-local
cucumber (9.0.2)
builder (~> 3.2, >= 3.2.4)
cucumber-ci-environment (~> 9.2, >= 9.2.0)
@@ -67,51 +41,25 @@ GEM
diff-lcs (1.5.0)
docile (1.4.0)
erubi (1.12.0)
falcon (0.42.3)
async
async-container (~> 0.16.0)
async-http (~> 0.57)
async-http-cache (~> 0.4.0)
async-io (~> 1.22)
build-environment (~> 1.13)
bundler
localhost (~> 1.1)
openssl (~> 3.0)
process-metrics (~> 0.2.0)
protocol-rack (~> 0.1)
samovar (~> 2.1)
ffi (1.16.2)
fiber-annotation (0.2.0)
fiber-local (1.0.0)
io-event (1.3.2)
localhost (1.1.10)
mapping (1.1.1)
matrix (0.4.2)
mini_mime (1.1.5)
mini_portile2 (2.8.4)
multi_test (1.1.0)
nio4r (2.5.9)
nokogiri (1.15.4)
mini_portile2 (~> 2.8.2)
racc (~> 1.4)
openssl (3.2.0)
process-metrics (0.2.1)
console (~> 1.8)
samovar (~> 2.1)
protocol-hpack (1.4.2)
protocol-http (0.24.7)
protocol-http1 (0.15.1)
protocol-http (~> 0.22)
protocol-http2 (0.15.1)
protocol-hpack (~> 1.4)
protocol-http (~> 0.18)
protocol-rack (0.2.6)
protocol-http (~> 0.23)
rack (>= 1.0)
public_suffix (5.0.3)
puma (6.4.0)
nio4r (~> 2.0)
racc (1.7.1)
rack (3.0.8)
rack-test (2.1.0)
rack (>= 1.3)
rackup (2.1.0)
rack (>= 3)
webrick (~> 1.8)
regexp_parser (2.8.1)
rexml (3.2.6)
roda (3.72.0)
@@ -130,9 +78,6 @@ GEM
rspec-support (~> 3.12.0)
rspec-support (3.12.1)
rubyzip (2.3.2)
samovar (2.2.0)
console (~> 1.0)
mapping (~> 1.0)
selenium-webdriver (4.13.1)
rexml (~> 3.2, >= 3.2.5)
rubyzip (>= 1.2.2, < 3.0)
@@ -150,8 +95,7 @@ GEM
sys-uname (1.2.3)
ffi (~> 1.1)
tilt (2.3.0)
timers (4.3.5)
traces (0.11.1)
webrick (1.8.1)
websocket (1.2.10)
xpath (3.2.0)
nokogiri (~> 1.8)
@@ -163,7 +107,8 @@ DEPENDENCIES
capybara (~> 3.39)
cucumber (~> 9.0)
erubi (~> 1.12)
falcon (~> 0.42.3)
puma (~> 6.4)
rackup (~> 2.1)
roda (~> 3.72)
rspec (~> 3.12)
selenium-webdriver (~> 4.13)
Vendored
+9 -4
View File
@@ -25,7 +25,12 @@ pipeline {
}
stage('Run tests') {
steps {
sh 'cucumber features --format html --out coverage/cucumber.html'
catchError(buildResult: 'UNSTABLE', stageResult: 'FAILURE') {
sh 'cucumber features --format html --out cucumber.html'
}
catchError(buildResult: 'UNSTABLE', stageResult: 'FAILURE') {
sh 'rspec spec --format html --out spec.html'
}
}
}
stage('Report results') {
@@ -35,10 +40,10 @@ pipeline {
allowMissing: false,
alwaysLinkToLastBuild: false,
keepAll: true,
reportDir: 'coverage',
reportFiles: 'cucumber.html, index.html',
reportDir: '.',
reportFiles: 'cucumber.html, spec.html, coverage/index.html',
reportName: 'Test Results',
reportTitles: 'Cucumber Results, Test Coverage'])
reportTitles: 'Cucumber Results, RSpec Results, Test Coverage'])
}
}
}
+61 -2
View File
@@ -2,11 +2,14 @@ require 'roda'
require 'securerandom'
require 'json'
require 'sequel'
require 'open-uri'
class App < Roda
plugin :sessions, secret: ENV.delete('APP_SESSION_SECRET')
plugin :render, escape: true
plugin :flash
plugin :json_parser
plugin :request_headers
DB = Sequel.sqlite("db/#{ENV['DB_NAME']}")
links = DB[:links]
@@ -27,18 +30,74 @@ class App < Roda
r.post "create" do
url = r.params['url']
if url.empty?
if url.nil? or url.empty?
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)
@message = "Link created"
end
code = links.filter(:url => url).first[:code]
@message ||= "Link exists"
@new_link = 'http://' + request.env['HTTP_HOST'] + '/' + links.filter(:url => url).first[:code]
@new_link = 'http://' + request.env['HTTP_HOST'] + '/' + code
view :create
end
r.on "links" do
r.post do
if 'application/json' != r.headers['CONTENT_TYPE']
response.status = 400
return {message: "not a valid json request"}.to_json
end
url = r.params['url']
if url.nil?
response.status = 400
return {message: "missing url parameter"}.to_json
end
if url.empty?
response.status = 400
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)
end
code = links.filter(:url => url).first[:code]
@new_link = 'http://' + request.env['HTTP_HOST'] + '/' + code
return {url: url, code: code, link: @new_link}.to_json
end
end
end
end
+1 -1
View File
@@ -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
+24
View File
@@ -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"
+101
View File
@@ -0,0 +1,101 @@
require 'simplecov'
SimpleCov.start
require_relative '../.env'
ENV["DB_NAME"] = "test_#{ENV["DB_NAME"]}"
require_relative '../app'
require 'rubygems'
require 'roda'
require 'sequel'
require 'rspec'
require 'rack/test'
# DB initialization
Sequel.extension :migration
Sequel.sqlite("db/#{ENV['DB_NAME']}") do |db|
Sequel::Migrator.apply(db, "db/migrations")
end
def app
App
end
describe "Submit API request to create new link" do
include Rack::Test::Methods
before :each do
@links = Sequel.sqlite("db/#{ENV['DB_NAME']}")[:links]
end
after :each do
@links.delete
end
it "should return link data in json format when a valid url is submitted" do
data = {
url: 'http://google.com'
}
post('/links', data.to_json, "CONTENT_TYPE" => "application/json")
expect(last_response).to be_ok
response_json = JSON.parse(last_response.body)
expect(response_json['url']).to eq(data[:url])
expect(response_json['code']).not_to eq(nil)
expect(response_json['link']).to include(response_json['code'])
end
it "should return with a 400 status and 'invalid url parameter' message when an empty url is submitted" do
data = {
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 'missing url parameter' message when an empty url is submitted" do
data = {
}
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('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