diff --git a/source/.rspec b/source/.rspec
new file mode 100644
index 0000000..c99d2e7
--- /dev/null
+++ b/source/.rspec
@@ -0,0 +1 @@
+--require spec_helper
diff --git a/source/Gemfile b/source/Gemfile
index 9627b8b..f7aad95 100644
--- a/source/Gemfile
+++ b/source/Gemfile
@@ -39,3 +39,8 @@ gem 'spring', group: :development
# gem 'debugger', group: [:development, :test]
gem 'rspec-rails', group: [:development, :test]
+ gem 'pry-rails', :group => [:development, :test]
+
+ group :development, :test do
+ gem "factory_girl_rails", "~> 4.0"
+ end
diff --git a/source/Gemfile.lock b/source/Gemfile.lock
index fcf8b98..8c7b8c0 100644
--- a/source/Gemfile.lock
+++ b/source/Gemfile.lock
@@ -28,33 +28,48 @@ GEM
thread_safe (~> 0.1)
tzinfo (~> 1.1)
arel (5.0.1.20140414130214)
- builder (3.2.2)
+ builder (3.2.3)
+ coderay (1.1.1)
coffee-rails (4.0.1)
coffee-script (>= 2.2.0)
railties (>= 4.0.0, < 5.0)
- coffee-script (2.3.0)
+ coffee-script (2.4.1)
coffee-script-source
execjs
- coffee-script-source (1.8.0)
- diff-lcs (1.2.5)
+ coffee-script-source (1.12.2)
+ diff-lcs (1.3)
erubis (2.7.0)
- execjs (2.2.1)
+ execjs (2.7.0)
+ factory_girl (4.8.0)
+ activesupport (>= 3.0.0)
+ factory_girl_rails (4.8.0)
+ factory_girl (~> 4.8.0)
+ railties (>= 3.0.0)
hike (1.2.3)
- i18n (0.6.11)
- jbuilder (2.2.2)
- activesupport (>= 3.0.0, < 5)
- multi_json (~> 1.2)
- jquery-rails (3.1.2)
+ i18n (0.8.6)
+ jbuilder (2.6.4)
+ activesupport (>= 3.0.0)
+ multi_json (>= 1.2)
+ jquery-rails (3.1.4)
railties (>= 3.0, < 5.0)
thor (>= 0.14, < 2.0)
- json (1.8.1)
- mail (2.6.1)
- mime-types (>= 1.16, < 3)
- mime-types (2.4.1)
- minitest (5.4.2)
- multi_json (1.10.1)
- rack (1.5.2)
- rack-test (0.6.2)
+ json (1.8.6)
+ mail (2.6.6)
+ mime-types (>= 1.16, < 4)
+ method_source (0.8.2)
+ mime-types (3.1)
+ mime-types-data (~> 3.2015)
+ mime-types-data (3.2016.0521)
+ minitest (5.10.2)
+ multi_json (1.12.1)
+ pry (0.10.4)
+ coderay (~> 1.1.0)
+ method_source (~> 0.8.1)
+ slop (~> 3.4)
+ pry-rails (0.3.6)
+ pry (>= 0.10.4)
+ rack (1.5.5)
+ rack-test (0.6.3)
rack (>= 1.0)
rails (4.1.6)
actionmailer (= 4.1.6)
@@ -71,63 +86,66 @@ GEM
activesupport (= 4.1.6)
rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0)
- rake (10.3.2)
- rdoc (4.1.2)
- json (~> 1.4)
- rspec-core (3.1.6)
- rspec-support (~> 3.1.0)
- rspec-expectations (3.1.2)
+ rake (12.0.0)
+ rdoc (4.3.0)
+ rspec-core (3.6.0)
+ rspec-support (~> 3.6.0)
+ rspec-expectations (3.6.0)
diff-lcs (>= 1.2.0, < 2.0)
- rspec-support (~> 3.1.0)
- rspec-mocks (3.1.3)
- rspec-support (~> 3.1.0)
- rspec-rails (3.1.0)
+ rspec-support (~> 3.6.0)
+ rspec-mocks (3.6.0)
+ diff-lcs (>= 1.2.0, < 2.0)
+ rspec-support (~> 3.6.0)
+ rspec-rails (3.6.0)
actionpack (>= 3.0)
activesupport (>= 3.0)
railties (>= 3.0)
- rspec-core (~> 3.1.0)
- rspec-expectations (~> 3.1.0)
- rspec-mocks (~> 3.1.0)
- rspec-support (~> 3.1.0)
- rspec-support (3.1.2)
+ rspec-core (~> 3.6.0)
+ rspec-expectations (~> 3.6.0)
+ rspec-mocks (~> 3.6.0)
+ rspec-support (~> 3.6.0)
+ rspec-support (3.6.0)
sass (3.2.19)
- sass-rails (4.0.3)
+ sass-rails (4.0.5)
railties (>= 4.0.0, < 5.0)
- sass (~> 3.2.0)
- sprockets (~> 2.8, <= 2.11.0)
+ sass (~> 3.2.2)
+ sprockets (~> 2.8, < 3.0)
sprockets-rails (~> 2.0)
- sdoc (0.4.1)
+ sdoc (0.4.2)
json (~> 1.7, >= 1.7.7)
rdoc (~> 4.0)
- spring (1.1.3)
- sprockets (2.11.0)
+ slop (3.6.0)
+ spring (1.7.2)
+ sprockets (2.12.4)
hike (~> 1.2)
multi_json (~> 1.0)
rack (~> 1.0)
tilt (~> 1.1, != 1.3.0)
- sprockets-rails (2.2.0)
+ sprockets-rails (2.3.3)
actionpack (>= 3.0)
activesupport (>= 3.0)
sprockets (>= 2.8, < 4.0)
- sqlite3 (1.3.9)
- thor (0.19.1)
- thread_safe (0.3.4)
+ sqlite3 (1.3.13)
+ thor (0.19.4)
+ thread_safe (0.3.6)
tilt (1.4.1)
- turbolinks (2.4.0)
- coffee-rails
- tzinfo (1.2.2)
+ turbolinks (5.0.1)
+ turbolinks-source (~> 5)
+ turbolinks-source (5.0.3)
+ tzinfo (1.2.3)
thread_safe (~> 0.1)
- uglifier (2.5.3)
- execjs (>= 0.3.0)
- json (>= 1.8.0)
+ uglifier (3.2.0)
+ execjs (>= 0.3.0, < 3)
PLATFORMS
ruby
DEPENDENCIES
coffee-rails (~> 4.0.0)
+ factory_girl_rails (~> 4.0)
jbuilder (~> 2.0)
jquery-rails
+ pry-rails
rails (= 4.1.6)
rspec-rails
sass-rails (~> 4.0.3)
@@ -136,3 +154,6 @@ DEPENDENCIES
sqlite3
turbolinks
uglifier (>= 1.3.0)
+
+BUNDLED WITH
+ 1.15.1
diff --git a/source/app/assets/javascripts/links.js.coffee b/source/app/assets/javascripts/links.js.coffee
new file mode 100644
index 0000000..e69de29
diff --git a/source/app/assets/javascripts/sessions.js b/source/app/assets/javascripts/sessions.js
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/source/app/assets/javascripts/sessions.js
@@ -0,0 +1 @@
+
diff --git a/source/app/assets/javascripts/sessions.js.coffee b/source/app/assets/javascripts/sessions.js.coffee
deleted file mode 100644
index 24f83d1..0000000
--- a/source/app/assets/javascripts/sessions.js.coffee
+++ /dev/null
@@ -1,3 +0,0 @@
-# Place all the behaviors and hooks related to the matching controller here.
-# All this logic will automatically be available in application.js.
-# You can use CoffeeScript in this file: http://coffeescript.org/
diff --git a/source/app/assets/stylesheets/links.css.scss b/source/app/assets/stylesheets/links.css.scss
new file mode 100644
index 0000000..81ec94b
--- /dev/null
+++ b/source/app/assets/stylesheets/links.css.scss
@@ -0,0 +1,3 @@
+// Place all the styles related to the links controller here.
+// They will automatically be included in application.css.
+// You can use Sass (SCSS) here: http://sass-lang.com/
diff --git a/source/app/assets/stylesheets/scaffolds.css.scss b/source/app/assets/stylesheets/scaffolds.css.scss
new file mode 100644
index 0000000..d573589
--- /dev/null
+++ b/source/app/assets/stylesheets/scaffolds.css.scss
@@ -0,0 +1,88 @@
+body {
+ background-color: #fff;
+ color: #333;
+ font-family: verdana, arial, helvetica, sans-serif;
+ font-size: 13px;
+ line-height: 18px;
+ text-align: center;
+}
+
+hr {
+ width: 65%;
+}
+
+table {
+ width: 30%;
+ margin-left: auto;
+ margin-right: auto;
+ font-size: 20px;
+}
+
+input {
+ text-align: center;
+ font-size: 15px;
+}
+
+p, ol, ul, td {
+ text-align: center;
+ font-family: verdana, arial, helvetica, sans-serif;
+ font-size: 20px;
+ line-height: 18px;
+ //border: 1px solid black
+}
+
+pre {
+ background-color: #eee;
+ padding: 10px;
+ font-size: 11px;
+}
+
+a {
+ color: #000;
+ &:visited {
+ color: #666;
+ }
+ &:hover {
+ color: #fff;
+ background-color: #000;
+ }
+}
+
+div {
+ &.field, &.actions {
+ margin-bottom: 10px;
+ }
+}
+
+#notice {
+ color: green;
+}
+
+.field_with_errors {
+ padding: 2px;
+ background-color: red;
+ display: table;
+}
+
+#error_explanation {
+ width: 450px;
+ border: 2px solid red;
+ padding: 7px;
+ padding-bottom: 0;
+ margin-bottom: 20px;
+ background-color: #f0f0f0;
+ h2 {
+ text-align: left;
+ font-weight: bold;
+ padding: 5px 5px 5px 15px;
+ font-size: 12px;
+ margin: -7px;
+ margin-bottom: 0px;
+ background-color: #c00;
+ color: #fff;
+ }
+ ul li {
+ font-size: 12px;
+ list-style: square;
+ }
+}
diff --git a/source/app/controllers/links_controller.rb b/source/app/controllers/links_controller.rb
new file mode 100644
index 0000000..6a2d4aa
--- /dev/null
+++ b/source/app/controllers/links_controller.rb
@@ -0,0 +1,29 @@
+class LinksController < ApplicationController
+
+ def index
+ @links = Link.all
+ @link = Link.new
+ end
+
+ def show
+ @link = Link.find_by new_url: params[:new_url]
+ @link.update_column(:counter, @link.counter + 1)
+ redirect_to @link.old_url
+ end
+
+ def create
+ @link = Link.new(link_params)
+ respond_to do |format|
+ if @link.save
+ format.html { redirect_to links_path }
+ else
+ format.html { render :new }
+ end
+ end
+ end
+
+ private
+ def link_params
+ params.require(:link).permit(:old_url, :new_url, :counter)
+ end
+end
diff --git a/source/app/helpers/links_helper.rb b/source/app/helpers/links_helper.rb
new file mode 100644
index 0000000..f6bc988
--- /dev/null
+++ b/source/app/helpers/links_helper.rb
@@ -0,0 +1,2 @@
+module LinksHelper
+end
diff --git a/source/app/models/link.rb b/source/app/models/link.rb
new file mode 100644
index 0000000..7bf6362
--- /dev/null
+++ b/source/app/models/link.rb
@@ -0,0 +1,17 @@
+class Link < ActiveRecord::Base
+ before_save :assign
+
+ # validates :old_url, presence: true, format: { with: /.com|.org|.edu|.net|.uk/,
+ # message: "The filed must filled with a URL using .com, .net, .edu, .org, etc." }
+
+ def random_end(length=5)
+ chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
+ text = ''
+ length.times { text << chars[rand(chars.size)] }
+ text
+ end
+
+ def assign
+ self.new_url = random_end
+ end
+end
diff --git a/source/app/views/links/_form.html.erb b/source/app/views/links/_form.html.erb
new file mode 100644
index 0000000..ac1edd6
--- /dev/null
+++ b/source/app/views/links/_form.html.erb
@@ -0,0 +1,25 @@
+<%= form_for(@link) do |f| %>
+ <% if @link.errors.any? %>
+
+
<%= pluralize(@link.errors.count, "error") %> prohibited this link from being saved:
+
+
+ <% @link.errors.full_messages.each do |message| %>
+ - <%= message %>
+ <% end %>
+
+
+ <% end %>
+
+
+ <%= f.label :old_url %>
+ <%= f.text_field :old_url, id: :link_old %>
+
+
+ <%= f.label :new_url %>
+ <%= f.text_field :new_url, id: :link_new %>
+
+
+ <%= f.submit %>
+
+<% end %>
diff --git a/source/app/views/links/_link.json.jbuilder b/source/app/views/links/_link.json.jbuilder
new file mode 100644
index 0000000..179fd60
--- /dev/null
+++ b/source/app/views/links/_link.json.jbuilder
@@ -0,0 +1,2 @@
+json.extract! link, :id, :old_url, :new_url, :created_at, :updated_at
+json.url link_url(link, format: :json)
diff --git a/source/app/views/links/index.html.erb b/source/app/views/links/index.html.erb
new file mode 100644
index 0000000..c2d80c6
--- /dev/null
+++ b/source/app/views/links/index.html.erb
@@ -0,0 +1,30 @@
+Welcome To A Bitly Clone
+
+
Enter The Link You Want To Shorten, Then Press The 'Generate Shorter Link' Button To Get The Shortened Link
+<%= form_for @link do |f| %>
+
+
+ | Old URL |
+ <%= f.text_field :old_url, type: 'url', id: 'link_old' %> |
+ <%= f.submit 'Generate Shorter Link', id: 'sub_button', :class => 'button' %> |
+
+
+<% end %>
+
+
+
+
+
+ | Old URL |
+ |
+ New URL |
+ Times Clicked |
+ <% @links.each do |link| %>
+
+ | <%= link.old_url %> |
+ |
+ <%= link_to "localhost:3000/#{link.new_url}", link_path(new_url: link.new_url) %> |
+ <%= link.counter %> |
+
+ <% end %>
+
diff --git a/source/app/views/links/index.json.jbuilder b/source/app/views/links/index.json.jbuilder
new file mode 100644
index 0000000..3c37950
--- /dev/null
+++ b/source/app/views/links/index.json.jbuilder
@@ -0,0 +1 @@
+json.array! @links, partial: 'links/link', as: :link
diff --git a/source/app/views/links/new.html.erb b/source/app/views/links/new.html.erb
new file mode 100644
index 0000000..0dbb5e1
--- /dev/null
+++ b/source/app/views/links/new.html.erb
@@ -0,0 +1,25 @@
+<% if @link.errors.any? %>
+
+
<%= pluralize(@link.errors.count, "error") %> prohibited this link from being saved:
+
+
+ <% @link.errors.full_messages.each do |message| %>
+ - <%= message %>
+ <% end %>
+
+
+<% end %>
+
+There Was An Error
+
+
The Link You Entered Did Not Work, Read The Errors On The Top Of The Page, Then Re-Click The 'Generate Shorter Link' Button
+<%= form_for @link do |f| %>
+
+
+ | Old URL |
+ <%= f.text_field :old_url, type: 'url', id: 'link_old' %> |
+ <%= f.submit 'Generate Shorter Link', id: 'sub_button', :class => 'button' %> |
+
+
+<% end %>
+
diff --git a/source/config/routes.rb b/source/config/routes.rb
index 3f66539..b177882 100644
--- a/source/config/routes.rb
+++ b/source/config/routes.rb
@@ -1,56 +1,10 @@
Rails.application.routes.draw do
- # The priority is based upon order of creation: first created -> highest priority.
- # See how all your routes lay out with "rake routes".
- # You can have the root of your site routed with "root"
- # root 'welcome#index'
+ get '/links', to: 'links#index'
- # Example of regular route:
- # get 'products/:id' => 'catalog#view'
+ post '/links', to: 'links#create'
- # Example of named route that can be invoked with purchase_url(id: product.id)
- # get 'products/:id/purchase' => 'catalog#purchase', as: :purchase
+ get '/:new_url', to: 'links#show', as: :link
- # Example resource route (maps HTTP verbs to controller actions automatically):
- # resources :products
-
- # Example resource route with options:
- # resources :products do
- # member do
- # get 'short'
- # post 'toggle'
- # end
- #
- # collection do
- # get 'sold'
- # end
- # end
-
- # Example resource route with sub-resources:
- # resources :products do
- # resources :comments, :sales
- # resource :seller
- # end
-
- # Example resource route with more complex sub-resources:
- # resources :products do
- # resources :comments
- # resources :sales do
- # get 'recent', on: :collection
- # end
- # end
-
- # Example resource route with concerns:
- # concern :toggleable do
- # post 'toggle'
- # end
- # resources :posts, concerns: :toggleable
- # resources :photos, concerns: :toggleable
-
- # Example resource route within a namespace:
- # namespace :admin do
- # # Directs /admin/products/* to Admin::ProductsController
- # # (app/controllers/admin/products_controller.rb)
- # resources :products
- # end
+ root 'links#index'
end
diff --git a/source/db/migrate/20170714174434_create_links.rb b/source/db/migrate/20170714174434_create_links.rb
new file mode 100644
index 0000000..b9d2459
--- /dev/null
+++ b/source/db/migrate/20170714174434_create_links.rb
@@ -0,0 +1,10 @@
+class CreateLinks < ActiveRecord::Migration
+ def change
+ create_table :links do |t|
+ t.string :old_url
+ t.string :new_url
+
+ t.timestamps
+ end
+ end
+end
diff --git a/source/db/migrate/20170719124824_add_column_to_links.rb b/source/db/migrate/20170719124824_add_column_to_links.rb
new file mode 100644
index 0000000..3260329
--- /dev/null
+++ b/source/db/migrate/20170719124824_add_column_to_links.rb
@@ -0,0 +1,5 @@
+class AddColumnToLinks < ActiveRecord::Migration
+ def change
+ add_column :links, :counter, :integer, default: 0
+ end
+end
diff --git a/source/db/schema.rb b/source/db/schema.rb
new file mode 100644
index 0000000..b087964
--- /dev/null
+++ b/source/db/schema.rb
@@ -0,0 +1,24 @@
+# encoding: UTF-8
+# This file is auto-generated from the current state of the database. Instead
+# of editing this file, please use the migrations feature of Active Record to
+# incrementally modify your database, and then regenerate this schema definition.
+#
+# Note that this schema.rb definition is the authoritative source for your
+# database schema. If you need to create the application database on another
+# system, you should be using db:schema:load, not running all the migrations
+# from scratch. The latter is a flawed and unsustainable approach (the more migrations
+# you'll amass, the slower it'll run and the greater likelihood for issues).
+#
+# It's strongly recommended that you check this file into your version control system.
+
+ActiveRecord::Schema.define(version: 20170719124824) do
+
+ create_table "links", force: true do |t|
+ t.string "old_url"
+ t.string "new_url"
+ t.datetime "created_at"
+ t.datetime "updated_at"
+ t.integer "counter", default: 0
+ end
+
+end
diff --git a/source/spec/factories.rb b/source/spec/factories.rb
new file mode 100644
index 0000000..4cf2c36
--- /dev/null
+++ b/source/spec/factories.rb
@@ -0,0 +1,6 @@
+FactoryGirl.define do
+ factory :link do
+ old_url "http://google.com"
+ new_url nil
+ end
+end
diff --git a/source/spec/helpers/links_helper_spec.rb b/source/spec/helpers/links_helper_spec.rb
new file mode 100644
index 0000000..5170f24
--- /dev/null
+++ b/source/spec/helpers/links_helper_spec.rb
@@ -0,0 +1,15 @@
+require 'rails_helper'
+
+# Specs in this file have access to a helper object that includes
+# the LinksHelper. For example:
+#
+# describe LinksHelper do
+# describe "string concat" do
+# it "concats two strings with spaces" do
+# expect(helper.concat_strings("this","that")).to eq("this that")
+# end
+# end
+# end
+RSpec.describe LinksHelper, type: :helper do
+ pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/source/spec/models/link_spec.rb b/source/spec/models/link_spec.rb
new file mode 100644
index 0000000..0492a5f
--- /dev/null
+++ b/source/spec/models/link_spec.rb
@@ -0,0 +1,24 @@
+require 'rails_helper'
+
+RSpec.describe Link, type: :model do
+ describe '.random_end' do
+ let(:link) { FactoryGirl.create :link }
+
+ it 'returns random string' do
+ expect(link.random_end.class).to eq(String)
+ end
+
+ it 'is 5 characters long' do
+ expect(link.random_end.length).to eq(5)
+ end
+ end
+
+ context 'on creation' do
+ let(:link) { FactoryGirl.build :link }
+
+ it 'automatically creates a new link' do
+ link.save
+ expect(link.new_url).to_not eq(nil)
+ end
+ end
+end
diff --git a/source/spec/rails_helper.rb b/source/spec/rails_helper.rb
new file mode 100644
index 0000000..46ba8e0
--- /dev/null
+++ b/source/spec/rails_helper.rb
@@ -0,0 +1,57 @@
+# This file is copied to spec/ when you run 'rails generate rspec:install'
+require 'spec_helper'
+ENV['RAILS_ENV'] ||= 'test'
+require File.expand_path('../../config/environment', __FILE__)
+# Prevent database truncation if the environment is production
+abort("The Rails environment is running in production mode!") if Rails.env.production?
+require 'rspec/rails'
+# Add additional requires below this line. Rails is not loaded until this point!
+
+# Requires supporting ruby files with custom matchers and macros, etc, in
+# spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are
+# run as spec files by default. This means that files in spec/support that end
+# in _spec.rb will both be required and run as specs, causing the specs to be
+# run twice. It is recommended that you do not name files matching this glob to
+# end with _spec.rb. You can configure this pattern with the --pattern
+# option on the command line or in ~/.rspec, .rspec or `.rspec-local`.
+#
+# The following line is provided for convenience purposes. It has the downside
+# of increasing the boot-up time by auto-requiring all files in the support
+# directory. Alternatively, in the individual `*_spec.rb` files, manually
+# require only the support files necessary.
+#
+# Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }
+
+# Checks for pending migration and applies them before tests are run.
+# If you are not using ActiveRecord, you can remove this line.
+ActiveRecord::Migration.maintain_test_schema!
+
+RSpec.configure do |config|
+ # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
+ config.fixture_path = "#{::Rails.root}/spec/fixtures"
+
+ # If you're not using ActiveRecord, or you'd prefer not to run each of your
+ # examples within a transaction, remove the following line or assign false
+ # instead of true.
+ config.use_transactional_fixtures = true
+
+ # RSpec Rails can automatically mix in different behaviours to your tests
+ # based on their file location, for example enabling you to call `get` and
+ # `post` in specs under `spec/controllers`.
+ #
+ # You can disable this behaviour by removing the line below, and instead
+ # explicitly tag your specs with their type, e.g.:
+ #
+ # RSpec.describe UsersController, :type => :controller do
+ # # ...
+ # end
+ #
+ # The different available types are documented in the features, such as in
+ # https://relishapp.com/rspec/rspec-rails/docs
+ config.infer_spec_type_from_file_location!
+
+ # Filter lines from Rails gems in backtraces.
+ config.filter_rails_from_backtrace!
+ # arbitrary gems may also be filtered via:
+ # config.filter_gems_from_backtrace("gem name")
+end
diff --git a/source/spec/requests/links_spec.rb b/source/spec/requests/links_spec.rb
new file mode 100644
index 0000000..da3c2c0
--- /dev/null
+++ b/source/spec/requests/links_spec.rb
@@ -0,0 +1,10 @@
+require 'rails_helper'
+
+RSpec.describe "Links", type: :request do
+ describe "GET /links" do
+ xit "works! (now write some real specs)" do
+ get links_path
+ expect(response).to have_http_status(200)
+ end
+ end
+end
diff --git a/source/spec/routing/links_routing_spec.rb b/source/spec/routing/links_routing_spec.rb
new file mode 100644
index 0000000..4b5f773
--- /dev/null
+++ b/source/spec/routing/links_routing_spec.rb
@@ -0,0 +1,39 @@
+require "rails_helper"
+
+RSpec.describe LinksController, type: :routing do
+ describe "routing" do
+
+ xit "routes to #index" do
+ expect(:get => "/links").to route_to("links#index")
+ end
+
+ xit "routes to #new" do
+ expect(:get => "/links/new").to route_to("links#new")
+ end
+
+ xit "routes to #show" do
+ expect(:get => "/links/1").to route_to("links#show", :id => "1")
+ end
+
+ xit "routes to #edit" do
+ expect(:get => "/links/1/edit").to route_to("links#edit", :id => "1")
+ end
+
+ xit "routes to #create" do
+ expect(:post => "/links").to route_to("links#create")
+ end
+
+ xit "routes to #update via PUT" do
+ expect(:put => "/links/1").to route_to("links#update", :id => "1")
+ end
+
+ xit "routes to #update via PATCH" do
+ expect(:patch => "/links/1").to route_to("links#update", :id => "1")
+ end
+
+ xit "routes to #destroy" do
+ expect(:delete => "/links/1").to route_to("links#destroy", :id => "1")
+ end
+
+ end
+end
diff --git a/source/spec/spec_helper.rb b/source/spec/spec_helper.rb
new file mode 100644
index 0000000..c4c723c
--- /dev/null
+++ b/source/spec/spec_helper.rb
@@ -0,0 +1,97 @@
+# This file was generated by the `rails generate rspec:install` command. Conventionally, all
+# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
+# The generated `.rspec` file contains `--require spec_helper` which will cause
+# this file to always be loaded, without a need to explicitly require it in any
+# files.
+#
+# Given that it is always loaded, you are encouraged to keep this file as
+# light-weight as possible. Requiring heavyweight dependencies from this file
+# will add to the boot time of your test suite on EVERY test run, even for an
+# individual file that may not need all of that loaded. Instead, consider making
+# a separate helper file that requires the additional dependencies and performs
+# the additional setup, and require it from the spec files that actually need
+# it.
+#
+# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
+RSpec.configure do |config|
+ # rspec-expectations config goes here. You can use an alternate
+ # assertion/expectation library such as wrong or the stdlib/minitest
+ # assertions if you prefer.
+ config.formatter = :documentation
+ config.expect_with :rspec do |expectations|
+ # This option will default to `true` in RSpec 4. It makes the `description`
+ # and `failure_message` of custom matchers include text for helper methods
+ # defined using `chain`, e.g.:
+ # be_bigger_than(2).and_smaller_than(4).description
+ # # => "be bigger than 2 and smaller than 4"
+ # ...rather than:
+ # # => "be bigger than 2"
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
+ end
+
+ # rspec-mocks config goes here. You can use an alternate test double
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
+ config.mock_with :rspec do |mocks|
+ # Prevents you from mocking or stubbing a method that does not exist on
+ # a real object. This is generally recommended, and will default to
+ # `true` in RSpec 4.
+ mocks.verify_partial_doubles = true
+ end
+
+ # This option will default to `:apply_to_host_groups` in RSpec 4 (and will
+ # have no way to turn it off -- the option exists only for backwards
+ # compatibility in RSpec 3). It causes shared context metadata to be
+ # inherited by the metadata hash of host groups and examples, rather than
+ # triggering implicit auto-inclusion in groups with matching metadata.
+ config.shared_context_metadata_behavior = :apply_to_host_groups
+
+# The settings below are suggested to provide a good initial experience
+# with RSpec, but feel free to customize to your heart's content.
+=begin
+ # This allows you to limit a spec run to individual examples or groups
+ # you care about by tagging them with `:focus` metadata. When nothing
+ # is tagged with `:focus`, all examples get run. RSpec also provides
+ # aliases for `it`, `describe`, and `context` that include `:focus`
+ # metadata: `fit`, `fdescribe` and `fcontext`, respectively.
+ config.filter_run_when_matching :focus
+
+ # Allows RSpec to persist some state between runs in order to support
+ # the `--only-failures` and `--next-failure` CLI options. We recommend
+ # you configure your source control system to ignore this file.
+ config.example_status_persistence_file_path = "spec/examples.txt"
+
+ # Limits the available syntax to the non-monkey patched syntax that is
+ # recommended. For more details, see:
+ # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/
+ # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
+ # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode
+ config.disable_monkey_patching!
+
+ # Many RSpec users commonly either run the entire suite or an individual
+ # file, and it's useful to allow more verbose output when running an
+ # individual spec file.
+ if config.files_to_run.one?
+ # Use the documentation formatter for detailed output,
+ # unless a formatter has already been configured
+ # (e.g. via a command-line flag).
+ config.default_formatter = "doc"
+ end
+
+ # Print the 10 slowest examples and example groups at the
+ # end of the spec run, to help surface which specs are running
+ # particularly slow.
+ config.profile_examples = 10
+
+ # Run specs in random order to surface order dependencies. If you find an
+ # order dependency and want to debug it, you can fix the order by providing
+ # the seed, which is printed after each run.
+ # --seed 1234
+ config.order = :random
+
+ # Seed global randomization in this process using the `--seed` CLI option.
+ # Setting this allows you to use `--seed` to deterministically reproduce
+ # test failures related to randomization by passing the same `--seed` value
+ # as the one that triggered the failure.
+ Kernel.srand config.seed
+=end
+end
diff --git a/source/spec/views/links/edit.html.erb_spec.rb b/source/spec/views/links/edit.html.erb_spec.rb
new file mode 100644
index 0000000..4cc6c43
--- /dev/null
+++ b/source/spec/views/links/edit.html.erb_spec.rb
@@ -0,0 +1,21 @@
+require 'rails_helper'
+
+RSpec.describe "links/edit", type: :view do
+ before(:each) do
+ @link = assign(:link, Link.create!(
+ :old_url => "MyString",
+ :new_url => "MyString"
+ ))
+ end
+
+ xit "renders the edit link form" do
+ render
+
+ assert_select "form[action=?][method=?]", link_path(@link), "post" do
+
+ assert_select "input#link_old_url[name=?]", "link[old_url]"
+
+ assert_select "input#link_new_url[name=?]", "link[new_url]"
+ end
+ end
+end
diff --git a/source/spec/views/links/index.html.erb_spec.rb b/source/spec/views/links/index.html.erb_spec.rb
new file mode 100644
index 0000000..13404fa
--- /dev/null
+++ b/source/spec/views/links/index.html.erb_spec.rb
@@ -0,0 +1,22 @@
+require 'rails_helper'
+
+RSpec.describe "links/index", type: :view do
+ before(:each) do
+ assign(:links, [
+ Link.create!(
+ :old_url => "Old Url",
+ :new_url => "New Url"
+ ),
+ Link.create!(
+ :old_url => "Old Url",
+ :new_url => "New Url"
+ )
+ ])
+ end
+
+ xit "renders a list of links" do
+ render
+ assert_select "tr>td", :text => "Old Url".to_s, :count => 2
+ assert_select "tr>td", :text => "New Url".to_s, :count => 2
+ end
+end
diff --git a/source/spec/views/links/new.html.erb_spec.rb b/source/spec/views/links/new.html.erb_spec.rb
new file mode 100644
index 0000000..02908b3
--- /dev/null
+++ b/source/spec/views/links/new.html.erb_spec.rb
@@ -0,0 +1,21 @@
+require 'rails_helper'
+
+RSpec.describe "links/new", type: :view do
+ before(:each) do
+ assign(:link, Link.new(
+ :old_url => "MyString",
+ :new_url => "MyString"
+ ))
+ end
+
+ xit "renders new link form" do
+ render
+
+ assert_select "form[action=?][method=?]", links_path, "post" do
+
+ assert_select "input#link_old_url[name=?]", "link[old_url]"
+
+ assert_select "input#link_new_url[name=?]", "link[new_url]"
+ end
+ end
+end
diff --git a/source/spec/views/links/show.html.erb_spec.rb b/source/spec/views/links/show.html.erb_spec.rb
new file mode 100644
index 0000000..41e8f7e
--- /dev/null
+++ b/source/spec/views/links/show.html.erb_spec.rb
@@ -0,0 +1,16 @@
+require 'rails_helper'
+
+RSpec.describe "links/show", type: :view do
+ before(:each) do
+ @link = assign(:link, Link.create!(
+ :old_url => "Old Url",
+ :new_url => "New Url"
+ ))
+ end
+
+ xit "renders attributes in " do
+ render
+ expect(rendered).to match(/Old Url/)
+ expect(rendered).to match(/New Url/)
+ end
+end