+ <%= link_to image_tag("rails.png", alt: "Rails logo"),
+ 'http://rubyonrails.org/' %>
+<% end %>
\ No newline at end of file
diff --git a/app/views/user_mailer/account_activation.html.erb b/app/views/user_mailer/account_activation.html.erb
new file mode 100644
index 0000000..603ece3
--- /dev/null
+++ b/app/views/user_mailer/account_activation.html.erb
@@ -0,0 +1,7 @@
+
Sample App
+
Hi <%= @user.name %>,
+
+Welcome to the Sample App! Click on the link below to activate your account:
+
+<%= link_to "Activate", edit_account_activation_url(@user.activation_token,
+email: @user.email) %>
\ No newline at end of file
diff --git a/app/views/user_mailer/account_activation.text.erb b/app/views/user_mailer/account_activation.text.erb
new file mode 100644
index 0000000..4f11c68
--- /dev/null
+++ b/app/views/user_mailer/account_activation.text.erb
@@ -0,0 +1,3 @@
+Hi <%= @user.name %>,
+Welcome to the Sample App! Click on the link below to activate your account:
+<%= edit_account_activation_url(@user.activation_token, email: @user.email) %>
\ No newline at end of file
diff --git a/app/views/user_mailer/password_reset.html.erb b/app/views/user_mailer/password_reset.html.erb
new file mode 100644
index 0000000..f86d184
--- /dev/null
+++ b/app/views/user_mailer/password_reset.html.erb
@@ -0,0 +1,9 @@
+
+If you did not request your password to be reset, please ignore this email and
+your password will stay as it is.
+
\ No newline at end of file
diff --git a/app/views/user_mailer/password_reset.text.erb b/app/views/user_mailer/password_reset.text.erb
new file mode 100644
index 0000000..9c35b0d
--- /dev/null
+++ b/app/views/user_mailer/password_reset.text.erb
@@ -0,0 +1,5 @@
+To reset your password click the link below:
+<%= edit_password_reset_url(@user.reset_token, email: @user.email) %>
+This link will expire in two hours.
+If you did not request your password to be reset, please ignore this email and
+your password will stay as it is.
\ No newline at end of file
diff --git a/app/views/users/_follow.html.erb b/app/views/users/_follow.html.erb
new file mode 100644
index 0000000..de3d08d
--- /dev/null
+++ b/app/views/users/_follow.html.erb
@@ -0,0 +1,6 @@
+<%= form_for(current_user.active_relationships.
+ build(followed_id: @user.id),
+ remote: true) do |f| %>
+
<%= hidden_field_tag :followed_id, @user.id %>
+ <%= f.submit "Follow", class: "btn btn-primary" %>
+<% end %>
\ No newline at end of file
diff --git a/app/views/users/_follow_form.html.erb b/app/views/users/_follow_form.html.erb
new file mode 100644
index 0000000..6daf9f8
--- /dev/null
+++ b/app/views/users/_follow_form.html.erb
@@ -0,0 +1,9 @@
+<% unless current_user?(@user) %>
+
\ No newline at end of file
diff --git a/app/views/users/edit.html.erb b/app/views/users/edit.html.erb
index d87b2f5..4b5c789 100644
--- a/app/views/users/edit.html.erb
+++ b/app/views/users/edit.html.erb
@@ -1,6 +1,22 @@
-
\ No newline at end of file
diff --git a/app/views/users/index.html.erb b/app/views/users/index.html.erb
index 32c0d02..3c7738b 100644
--- a/app/views/users/index.html.erb
+++ b/app/views/users/index.html.erb
@@ -1,29 +1,10 @@
-
\ No newline at end of file
diff --git a/app/views/users/show_follow.html.erb b/app/views/users/show_follow.html.erb
new file mode 100644
index 0000000..333d582
--- /dev/null
+++ b/app/views/users/show_follow.html.erb
@@ -0,0 +1,30 @@
+<% provide(:title, @title) %>
+
+
+
+
<%= @title %>
+ <% if @users.any? %>
+
+ <%= render @users %>
+
+ <%= will_paginate %>
+ <% end %>
+
+
\ No newline at end of file
diff --git a/config/application.rb b/config/application.rb
index 1991721..4070adb 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -22,5 +22,7 @@ class Application < Rails::Application
# Do not swallow errors in after_commit/after_rollback callbacks.
config.active_record.raise_in_transactional_callbacks = true
+ # Include the authenticity token in remote forms.
+ config.action_view.embed_authenticity_token_in_remote_forms = true
end
end
diff --git a/config/environments/development.rb b/config/environments/development.rb
index b55e214..11054bc 100644
--- a/config/environments/development.rb
+++ b/config/environments/development.rb
@@ -22,6 +22,12 @@
# Raise an error on page load if there are pending migrations.
config.active_record.migration_error = :page_load
+
+
+ config.action_mailer.raise_delivery_errors = true
+ config.action_mailer.delivery_method = :test
+ host = 'localhost:3000'
+ config.action_mailer.default_url_options = { host: host }
# Debug mode disables concatenation and preprocessing of assets.
# This option may cause significant delays in view rendering with a large
# number of complex assets.
diff --git a/config/environments/test.rb b/config/environments/test.rb
index 1c19f08..58ff691 100644
--- a/config/environments/test.rb
+++ b/config/environments/test.rb
@@ -30,7 +30,7 @@
# The :test delivery method accumulates sent emails in the
# ActionMailer::Base.deliveries array.
config.action_mailer.delivery_method = :test
-
+ config.action_mailer.default_url_options = { host: 'localhost:3000' }
# Randomize the order test cases are executed.
config.active_support.test_order = :random
diff --git a/config/initializers/carrier_wave.rb b/config/initializers/carrier_wave.rb
new file mode 100644
index 0000000..c3aa2b8
--- /dev/null
+++ b/config/initializers/carrier_wave.rb
@@ -0,0 +1,11 @@
+if Rails.env.production?
+ CarrierWave.configure do |config|
+ config.fog_credentials = {
+ # Configuration for Amazon S3
+ :provider => 'AWS',
+ :aws_access_key_id => ENV['S3_ACCESS_KEY'],
+ :aws_secret_access_key => ENV['S3_SECRET_KEY']
+ }
+ config.fog_directory = ENV['S3_BUCKET']
+ end
+end
\ No newline at end of file
diff --git a/config/routes.rb b/config/routes.rb
index 7acdf2a..493cb86 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,17 +1,28 @@
Rails.application.routes.draw do
+ get 'password_resets/new'
+
+ get 'password_resets/edit'
+
root 'static_pages#home'
get 'help' => 'static_pages#help'
get 'about' => 'static_pages#about'
get 'contact' => 'static_pages#contact'
get 'signup' => 'users#new'
- post '/signup' => 'users#create'
+ #post '/signup' => 'users#create'
get 'login' => 'sessions#new'
post 'login' => 'sessions#create'
delete 'logout' => 'sessions#destroy'
- resources :microposts
- resources :users
+ resources :users do
+ member do
+ get :following, :followers
+ end
+ end
+ resources :account_activations, only: [:edit]
+ resources :microposts, only: [:create, :destroy]
+ resources :password_resets, only: [:new, :create, :edit, :update]
+ resources :relationships, only: [:create, :destroy]
# The priority is based upon order of creation: first created -> highest priority.
# See how all your routes lay out with "rake routes".
diff --git a/db/migrate/20160708090312_add_admin_to_users.rb b/db/migrate/20160708090312_add_admin_to_users.rb
new file mode 100644
index 0000000..e386d33
--- /dev/null
+++ b/db/migrate/20160708090312_add_admin_to_users.rb
@@ -0,0 +1,5 @@
+class AddAdminToUsers < ActiveRecord::Migration
+ def change
+ add_column :users, :admin, :boolean, default: false
+ end
+end
diff --git a/db/migrate/20160711062804_add_activation_to_users.rb b/db/migrate/20160711062804_add_activation_to_users.rb
new file mode 100644
index 0000000..b7b0abf
--- /dev/null
+++ b/db/migrate/20160711062804_add_activation_to_users.rb
@@ -0,0 +1,7 @@
+class AddActivationToUsers < ActiveRecord::Migration
+ def change
+ add_column :users, :activation_digest, :string
+ add_column :users, :activated, :boolean, default: false
+ add_column :users, :activated_at, :datetime
+ end
+end
diff --git a/db/migrate/20160707012303_create_microposts.rb b/db/migrate/20160712070613_create_microposts.rb
similarity index 53%
rename from db/migrate/20160707012303_create_microposts.rb
rename to db/migrate/20160712070613_create_microposts.rb
index 67117ba..75bcba8 100644
--- a/db/migrate/20160707012303_create_microposts.rb
+++ b/db/migrate/20160712070613_create_microposts.rb
@@ -2,9 +2,11 @@ class CreateMicroposts < ActiveRecord::Migration
def change
create_table :microposts do |t|
t.text :content
- t.integer :user_id
+ t.references :user, index: true, foreign_key: true
t.timestamps null: false
end
+ add_foreign_key :microposts, :users
+ add_index :microposts, [:user_id, :created_at]
end
end
diff --git a/db/migrate/20160712093058_add_picture_to_microposts.rb b/db/migrate/20160712093058_add_picture_to_microposts.rb
new file mode 100644
index 0000000..5433286
--- /dev/null
+++ b/db/migrate/20160712093058_add_picture_to_microposts.rb
@@ -0,0 +1,5 @@
+class AddPictureToMicroposts < ActiveRecord::Migration
+ def change
+ add_column :microposts, :picture, :string
+ end
+end
diff --git a/db/migrate/20160712155715_add_reset_to_users.rb b/db/migrate/20160712155715_add_reset_to_users.rb
new file mode 100644
index 0000000..f650b49
--- /dev/null
+++ b/db/migrate/20160712155715_add_reset_to_users.rb
@@ -0,0 +1,6 @@
+class AddResetToUsers < ActiveRecord::Migration
+ def change
+ add_column :users, :reset_digest, :string
+ add_column :users, :reset_sent_at, :date_time
+ end
+end
diff --git a/db/migrate/20160713061441_create_relationships.rb b/db/migrate/20160713061441_create_relationships.rb
new file mode 100644
index 0000000..530a27d
--- /dev/null
+++ b/db/migrate/20160713061441_create_relationships.rb
@@ -0,0 +1,13 @@
+class CreateRelationships < ActiveRecord::Migration
+ def change
+ create_table :relationships do |t|
+ t.integer :follower_id
+ t.integer :followed_id
+
+ t.timestamps null: false
+ end
+ add_index :relationships, :follower_id
+ add_index :relationships, :followed_id
+ add_index :relationships, [:follower_id, :followed_id], unique: true
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index a428c08..62308c5 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,22 +11,43 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 20160708032244) do
+ActiveRecord::Schema.define(version: 20160713061441) do
create_table "microposts", force: :cascade do |t|
t.text "content"
t.integer "user_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
+ t.string "picture"
end
+ add_index "microposts", ["user_id", "created_at"], name: "index_microposts_on_user_id_and_created_at"
+ add_index "microposts", ["user_id"], name: "index_microposts_on_user_id"
+
+ create_table "relationships", force: :cascade do |t|
+ t.integer "follower_id"
+ t.integer "followed_id"
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ end
+
+ add_index "relationships", ["followed_id"], name: "index_relationships_on_followed_id"
+ add_index "relationships", ["follower_id", "followed_id"], name: "index_relationships_on_follower_id_and_followed_id", unique: true
+ add_index "relationships", ["follower_id"], name: "index_relationships_on_follower_id"
+
create_table "users", force: :cascade do |t|
t.string "name"
t.string "email"
- t.datetime "created_at", null: false
- t.datetime "updated_at", null: false
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
t.string "password_digest"
t.string "remember_digest"
+ t.boolean "admin", default: false
+ t.string "activation_digest"
+ t.boolean "activated", default: false
+ t.datetime "activated_at"
+ t.string "reset_digest"
+ t.time "reset_sent_at"
end
add_index "users", ["email"], name: "index_users_on_email", unique: true
diff --git a/db/seeds.rb b/db/seeds.rb
index 4edb1e8..500bda1 100644
--- a/db/seeds.rb
+++ b/db/seeds.rb
@@ -5,3 +5,35 @@
#
# cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }])
# Mayor.create(name: 'Emanuel', city: cities.first)
+User.create!(name: "Example User",
+ email: "example@railstutorial.org",
+ password: "foobar",
+ password_confirmation: "foobar",
+ admin: true,
+ activated: true,
+ activated_at: Time.zone.now)
+99.times do |n|
+ name = Faker::Name.name
+ email = "example-#{n+1}@railstutorial.org"
+ password = "password"
+ User.create!(name: name,
+ email: email,
+ password: password,
+ password_confirmation: password,
+ activated: true,
+ activated_at: Time.zone.now)
+end
+
+users = User.order(:created_at).take(6)
+50.times do
+ content = Faker::Lorem.sentence(5)
+ users.each { |user| user.microposts.create!(content: content) }
+end
+
+# Following relationships
+users = User.all
+user = users.first
+following = users[2..50]
+followers = users[3..40]
+following.each { |followed| user.follow(followed) }
+followers.each { |follower| follower.follow(user) }
\ No newline at end of file
diff --git a/public/uploads/micropost/picture/301/HBLAB.png b/public/uploads/micropost/picture/301/HBLAB.png
new file mode 100644
index 0000000..c0c6ebb
Binary files /dev/null and b/public/uploads/micropost/picture/301/HBLAB.png differ
diff --git a/public/uploads/micropost/picture/303/1yeartruoc.png b/public/uploads/micropost/picture/303/1yeartruoc.png
new file mode 100644
index 0000000..2615ca0
Binary files /dev/null and b/public/uploads/micropost/picture/303/1yeartruoc.png differ
diff --git a/public/uploads/micropost/picture/306/treat.png b/public/uploads/micropost/picture/306/treat.png
new file mode 100644
index 0000000..955ce64
Binary files /dev/null and b/public/uploads/micropost/picture/306/treat.png differ
diff --git a/public/uploads/micropost/picture/307/cover.jpg b/public/uploads/micropost/picture/307/cover.jpg
new file mode 100644
index 0000000..6cba581
Binary files /dev/null and b/public/uploads/micropost/picture/307/cover.jpg differ
diff --git a/public/uploads/tmp/1468396517-3921-6458/bomb.png b/public/uploads/tmp/1468396517-3921-6458/bomb.png
new file mode 100644
index 0000000..6be49bb
Binary files /dev/null and b/public/uploads/tmp/1468396517-3921-6458/bomb.png differ
diff --git a/public/uploads/tmp/1468396533-3921-7387/treat.png b/public/uploads/tmp/1468396533-3921-7387/treat.png
new file mode 100644
index 0000000..258827c
Binary files /dev/null and b/public/uploads/tmp/1468396533-3921-7387/treat.png differ
diff --git a/test/controllers/account_activation_controller_test.rb b/test/controllers/account_activation_controller_test.rb
new file mode 100644
index 0000000..1a66567
--- /dev/null
+++ b/test/controllers/account_activation_controller_test.rb
@@ -0,0 +1,7 @@
+require 'test_helper'
+
+class AccountActivationControllerTest < ActionController::TestCase
+ # test "the truth" do
+ # assert true
+ # end
+end
diff --git a/test/controllers/microposts_controller_test.rb b/test/controllers/microposts_controller_test.rb
index be8f376..a876fa6 100644
--- a/test/controllers/microposts_controller_test.rb
+++ b/test/controllers/microposts_controller_test.rb
@@ -1,49 +1,31 @@
require 'test_helper'
class MicropostsControllerTest < ActionController::TestCase
- setup do
- @micropost = microposts(:one)
- end
-
- test "should get index" do
- get :index
- assert_response :success
- assert_not_nil assigns(:microposts)
- end
-
- test "should get new" do
- get :new
- assert_response :success
- end
-
- test "should create micropost" do
- assert_difference('Micropost.count') do
- post :create, micropost: { content: @micropost.content, user_id: @micropost.user_id }
- end
-
- assert_redirected_to micropost_path(assigns(:micropost))
- end
-
- test "should show micropost" do
- get :show, id: @micropost
- assert_response :success
- end
-
- test "should get edit" do
- get :edit, id: @micropost
- assert_response :success
- end
-
- test "should update micropost" do
- patch :update, id: @micropost, micropost: { content: @micropost.content, user_id: @micropost.user_id }
- assert_redirected_to micropost_path(assigns(:micropost))
- end
-
- test "should destroy micropost" do
- assert_difference('Micropost.count', -1) do
- delete :destroy, id: @micropost
- end
-
- assert_redirected_to microposts_path
- end
+ # test "the truth" do
+ # assert true
+ # end
+ def setup
+ @micropost = microposts(:orange)
+ end
+ test "should redirect create when not logged in" do
+ assert_no_difference 'Micropost.count' do
+ post :create, micropost: { content: "Lorem ipsum" }
+ end
+ assert_redirected_to login_url
+ end
+ test "should redirect destroy when not logged in" do
+ assert_no_difference 'Micropost.count' do
+ delete :destroy, id: @micropost
+ end
+ assert_redirected_to login_url
+ end
+
+ test "should redirect destroy for wrong micropost" do
+ log_in_as(users(:michael))
+ micropost = microposts(:ants)
+ assert_no_difference 'Micropost.count' do
+ delete :destroy, id: micropost
+ end
+ assert_redirected_to root_url
+ end
end
diff --git a/test/controllers/relationships_controller_test.rb b/test/controllers/relationships_controller_test.rb
new file mode 100644
index 0000000..28b6975
--- /dev/null
+++ b/test/controllers/relationships_controller_test.rb
@@ -0,0 +1,15 @@
+require 'test_helper'
+class RelationshipsControllerTest < ActionController::TestCase
+ test "create should require logged-in user" do
+ assert_no_difference 'Relationship.count' do
+ post :create
+ end
+ assert_redirected_to login_url
+ end
+ test "destroy should require logged-in user" do
+ assert_no_difference 'Relationship.count' do
+ delete :destroy, id: relationships(:one)
+ end
+ assert_redirected_to login_url
+ end
+end
\ No newline at end of file
diff --git a/test/controllers/users_controller_test.rb b/test/controllers/users_controller_test.rb
index 7d2d9b1..876b1fc 100644
--- a/test/controllers/users_controller_test.rb
+++ b/test/controllers/users_controller_test.rb
@@ -1,9 +1,60 @@
require 'test_helper'
class UsersControllerTest < ActionController::TestCase
- test "should get new" do
- get :new
- assert_response :success
+ def setup
+ @user = users(:michael)
+ @other_user = users(:archer)
+ end
+ test "should redirect index when not logged in" do
+ get :index
+ assert_redirected_to login_url
+ end
+
+ test "should redirect edit when not logged in" do
+ get :edit, id: @user
+ assert_not flash.empty?
+ assert_redirected_to login_url
+ end
+
+ test "should redirect update when not logged in" do
+ patch :update, id: @user, user: { name: @user.name, email: @user.email }
+ assert_not flash.empty?
+ assert_redirected_to login_url
+ end
+
+ test "should redirect edit when logged in as wrong user" do
+ log_in_as(@other_user)
+ get :edit, id: @user
+ assert flash.empty?
+ assert_redirected_to root_url
end
+ test "should redirect update when logged in as wrong user" do
+ log_in_as(@other_user)
+ patch :update, id: @user, user: { name: @user.name, email: @user.email }
+ assert flash.empty?
+ assert_redirected_to root_url
+ end
+
+ test "should redirect destroy when not logged in" do
+ assert_no_difference 'User.count' do
+ delete :destroy, id: @user
+ end
+ assert_redirected_to login_url
+ end
+ test "should redirect destroy when logged in as a non-admin" do
+ log_in_as(@other_user)
+ assert_no_difference 'User.count' do
+ delete :destroy, id: @user
+ end
+ assert_redirected_to root_url
+ end
+ test "should redirect following when not logged in" do
+ get :following, id: @user
+ assert_redirected_to login_url
+ end
+ test "should redirect followers when not logged in" do
+ get :followers, id: @user
+ assert_redirected_to login_url
+ end
end
diff --git a/test/fixtures/microposts.yml b/test/fixtures/microposts.yml
index a5153b6..2a1fcaa 100644
--- a/test/fixtures/microposts.yml
+++ b/test/fixtures/microposts.yml
@@ -1,9 +1,46 @@
# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
-one:
- content: MyText
- user_id:
+orange:
+ content: "I just ate an orange!"
+ created_at: <%= 10.minutes.ago %>
+ user: michael
+
+tau_manifesto:
+ content: "Check out the @tauday site by @mhartl: http://tauday.com"
+ created_at: <%= 3.years.ago %>
+ user: michael
+
+cat_video:
+ content: "Sad cats are sad: http://youtu.be/PKffm2uI4dk"
+ created_at: <%= 2.hours.ago %>
+ user: michael
+
+most_recent:
+ content: "Writing a short test"
+ created_at: <%= Time.zone.now %>
+ user: michael
+
+<% 30.times do |n| %>
+micropost_<%= n %>:
+ content: <%= Faker::Lorem.sentence(5) %>
+ created_at: <%= 42.days.ago %>
+ user: michael
+<% end %>
+
+ants:
+ content: "Oh, is that what you want? Because that's how you get ants!"
+ created_at: <%= 2.years.ago %>
+ user: archer
+zone:
+ content: "Danger zone!"
+ created_at: <%= 3.days.ago %>
+ user: archer
+tone:
+ content: "I'm sorry. Your words made sense, but your sarcastic tone did not."
+ created_at: <%= 10.minutes.ago %>
+ user: lana
+van:
+ content: "Dude, this van's, like, rolling probable cause."
+ created_at: <%= 4.hours.ago %>
+ user: lana
-two:
- content: MyText
- user_id:
diff --git a/test/fixtures/relationships.yml b/test/fixtures/relationships.yml
new file mode 100644
index 0000000..1c4f106
--- /dev/null
+++ b/test/fixtures/relationships.yml
@@ -0,0 +1,13 @@
+# empty
+one:
+ follower: Johnny Corkery
+ followed: lana
+two:
+ follower: michael
+ followed: mallory
+three:
+ follower: lana
+ followed: michael
+four:
+ follower: archer
+ followed: michael
\ No newline at end of file
diff --git a/test/fixtures/users.yml b/test/fixtures/users.yml
index 1294a78..c515071 100644
--- a/test/fixtures/users.yml
+++ b/test/fixtures/users.yml
@@ -1,4 +1,33 @@
michael:
name: Michael Example
email: michael@example.com
- password_digest: <%= User.digest('password') %>
\ No newline at end of file
+ password_digest: <%= User.digest('password') %>
+ admin: true
+ activated: true
+ activated_at: <%= Time.zone.now %>
+archer:
+ name: Sterling Archer
+ email: duchess@example.gov
+ password_digest: <%= User.digest('password') %>
+ activated: true
+ activated_at: <%= Time.zone.now %>
+lana:
+ name: Lana Kane
+ email: hands@example.gov
+ password_digest: <%= User.digest('password') %>
+ activated: true
+ activated_at: <%= Time.zone.now %>
+mallory:
+ name: Mallory Archer
+ email: boss@example.gov
+ password_digest: <%= User.digest('password') %>
+ activated: true
+ activated_at: <%= Time.zone.now %>
+<% 30.times do |n| %>
+user_<%= n %>:
+ name: <%= "User #{n}" %>
+ email: <%= "user-#{n}@example.com" %>
+ password_digest: <%= User.digest('password') %>
+ activated: true
+ activated_at: <%= Time.zone.now %>
+<% end %>
\ No newline at end of file
diff --git a/test/integration/following_test.rb b/test/integration/following_test.rb
new file mode 100644
index 0000000..08396fc
--- /dev/null
+++ b/test/integration/following_test.rb
@@ -0,0 +1,48 @@
+require 'test_helper'
+class FollowingTest < ActionDispatch::IntegrationTest
+ def setup
+ @user = users(:michael)
+ @other = users(:archer)
+ log_in_as(@user)
+ end
+ test "following page" do
+ get following_user_path(@user)
+ assert_not @user.following.empty?
+ assert_match @user.following.count.to_s, response.body
+ @user.following.each do |user|
+ assert_select "a[href=?]", user_path(user)
+ end
+ end
+ test "followers page" do
+ get followers_user_path(@user)
+ assert_not @user.followers.empty?
+ assert_match @user.followers.count.to_s, response.body
+ @user.followers.each do |user|
+ assert_select "a[href=?]", user_path(user)
+ end
+ end
+ test "should follow a user the standard way" do
+ assert_difference '@user.following.count', 1 do
+ post relationships_path, followed_id: @other.id
+ end
+ end
+ test "should follow a user with Ajax" do
+ assert_difference '@user.following.count', 1 do
+ xhr :post, relationships_path, followed_id: @other.id
+ end
+ end
+ test "should unfollow a user the standard way" do
+ @user.follow(@other)
+ relationship = @user.active_relationships.find_by(followed_id: @other.id)
+ assert_difference '@user.following.count', -1 do
+ delete relationship_path(relationship)
+ end
+ end
+ test "should unfollow a user with Ajax" do
+ @user.follow(@other)
+ relationship = @user.active_relationships.find_by(followed_id: @other.id)
+ assert_difference '@user.following.count', -1 do
+ xhr :delete, relationship_path(relationship)
+ end
+ end
+end
\ No newline at end of file
diff --git a/test/integration/microposts_interface_test.rb b/test/integration/microposts_interface_test.rb
new file mode 100644
index 0000000..39bacb3
--- /dev/null
+++ b/test/integration/microposts_interface_test.rb
@@ -0,0 +1,37 @@
+require 'test_helper'
+
+class MicropostsInterfaceTest < ActionDispatch::IntegrationTest
+ # test "the truth" do
+ # assert true
+ # end
+ def setup
+ @user = users(:michael)
+ end
+ test "micropost interface" do
+ log_in_as(@user)
+ get root_path
+ assert_select 'div.pagination'
+ # Invalid submission
+ assert_no_difference 'Micropost.count' do
+ post microposts_path, micropost: { content: "" }
+ end
+ assert_select 'div#error_explanation'
+ # Valid submission
+ content = "This micropost really ties the room together"
+ assert_difference 'Micropost.count', 1 do
+ post microposts_path, micropost: { content: content }
+ end
+ assert_redirected_to root_url
+ follow_redirect!
+ assert_match content, response.body
+ # Delete a post.
+ assert_select 'a', text: 'delete'
+ first_micropost = @user.microposts.paginate(page: 1).first
+ assert_difference 'Micropost.count', -1 do
+ delete micropost_path(first_micropost)
+ end
+ # Visit a different user.
+ get user_path(users(:archer))
+ assert_select 'a', text: 'delete', count: 0
+ end
+end
diff --git a/test/integration/password_reset_test.rb b/test/integration/password_reset_test.rb
new file mode 100644
index 0000000..d2b91de
--- /dev/null
+++ b/test/integration/password_reset_test.rb
@@ -0,0 +1,59 @@
+require 'test_helper'
+class PasswordResetsTest < ActionDispatch::IntegrationTest
+ def setup
+ ActionMailer::Base.deliveries.clear
+ @user = users(:michael)
+ end
+ test "password resets" do
+ get new_password_reset_path
+ assert_template 'password_resets/new'
+ # Invalid email
+ post password_resets_path, password_reset: { email: "" }
+ assert_not flash.empty?
+ assert_template 'password_resets/new'
+ # Valid email
+ post password_resets_path, password_reset: { email: @user.email }
+ assert_not_equal @user.reset_digest, @user.reload.reset_digest
+ assert_equal 1, ActionMailer::Base.deliveries.size
+ assert_not flash.empty?
+ assert_redirected_to root_url
+ # Password reset form
+ user = assigns(:user)
+ # Wrong email
+ get edit_password_reset_path(user.reset_token, email: "")
+ assert_redirected_to root_url
+ # Inactive user
+ user.toggle!(:activated)
+ get edit_password_reset_path(user.reset_token, email: user.email)
+ assert_redirected_to root_url
+ user.toggle!(:activated)
+ # Right email, wrong token
+ get edit_password_reset_path('wrong token', email: user.email)
+ assert_redirected_to root_url
+ # Right email, right token
+ get edit_password_reset_path(user.reset_token, email: user.email)
+ assert_template 'password_resets/edit'
+ assert_select "input[name=email][type=hidden][value=?]", user.email
+ # Invalid password & confirmation
+ patch password_reset_path(user.reset_token),
+ email: user.email,
+ user: { password: "foobaz",
+ password_confirmation: "barquux" }
+ assert_select 'div#error_explanation'
+ # Blank password
+ patch password_reset_path(user.reset_token),
+ email: user.email,
+ user: { password: " ",
+ password_confirmation: "foobar" }
+ assert_not flash.empty?
+ assert_template 'password_resets/edit'
+ # Valid password & confirmation
+ patch password_reset_path(user.reset_token),
+ email: user.email,
+ user: { password: "foobaz",
+ password_confirmation: "foobaz" }
+ assert is_logged_in?
+ assert_not flash.empty?
+ assert_redirected_to user
+ end
+end
\ No newline at end of file
diff --git a/test/integration/users_edit_test.rb b/test/integration/users_edit_test.rb
new file mode 100644
index 0000000..68b0115
--- /dev/null
+++ b/test/integration/users_edit_test.rb
@@ -0,0 +1,54 @@
+require 'test_helper'
+
+class UsersEditTest < ActionDispatch::IntegrationTest
+ # test "the truth" do
+ # assert true
+ # end
+ def setup
+ @user = users(:michael)
+ end
+ test "unsuccessful edit" do
+ log_in_as(@user)
+ get edit_user_path(@user)
+ assert_template 'users/edit'
+ patch user_path(@user), user: { name: "",
+ email: "foo@invalid",
+ password: "foo",
+ password_confirmation: "bar" }
+ assert_template 'users/edit'
+ end
+ test "successful edit" do
+ log_in_as(@user)
+ get edit_user_path(@user)
+ assert_template 'users/edit'
+ name = "Foo Bar"
+ email = "foo@bar.com"
+ patch user_path(@user), user: { name: name,
+ email: email,
+ password: "",
+ password_confirmation: "" }
+ assert_not flash.empty?
+ assert_redirected_to @user
+ @user.reload
+ assert_equal @user.name, name
+ assert_equal @user.email, email
+ end
+
+
+ test "successful edit with friendly forwarding" do
+ get edit_user_path(@user)
+ log_in_as(@user)
+ assert_redirected_to edit_user_path(@user)
+ name = "Foo Bar"
+ email = "foo@bar.com"
+ patch user_path(@user), user: { name: name,
+ email: email,
+ password: "foobar",
+ password_confirmation: "foobar" }
+ assert_not flash.empty?
+ assert_redirected_to @user
+ @user.reload
+ assert_equal @user.name, name
+ assert_equal @user.email, email
+ end
+end
diff --git a/test/integration/users_index_test.rb b/test/integration/users_index_test.rb
new file mode 100644
index 0000000..91b7058
--- /dev/null
+++ b/test/integration/users_index_test.rb
@@ -0,0 +1,33 @@
+require 'test_helper'
+
+class UsersIndexTest < ActionDispatch::IntegrationTest
+ # test "the truth" do
+ # assert true
+ # end
+ def setup
+ @admin = users(:michael)
+ @non_admin = users(:archer)
+ end
+ test "index as admin including pagination and delete links" do
+ log_in_as(@admin)
+ get users_path
+ assert_template 'users/index'
+ assert_select 'div.pagination'
+ first_page_of_users = User.paginate(page: 1)
+ first_page_of_users.each do |user|
+ assert_select 'a[href=?]', user_path(user), text: user.name
+ unless user == @admin
+ assert_select 'a[href=?]', user_path(user), text: 'delete',
+ method: :delete
+ end
+ end
+ assert_difference 'User.count', -1 do
+ delete user_path(@non_admin)
+ end
+ end
+ test "index as non-admin" do
+ log_in_as(@non_admin)
+ get users_path
+ assert_select 'a', text: 'delete', count: 0
+ end
+end
diff --git a/test/integration/users_profile_test.rb b/test/integration/users_profile_test.rb
new file mode 100644
index 0000000..c7af388
--- /dev/null
+++ b/test/integration/users_profile_test.rb
@@ -0,0 +1,19 @@
+require 'test_helper'
+class UsersProfileTest < ActionDispatch::IntegrationTest
+ include ApplicationHelper
+ def setup
+ @user = users(:michael)
+ end
+ test "profile display" do
+ get user_path(@user)
+ assert_template 'users/show'
+ assert_select 'title', full_title(@user.name)
+ assert_select 'h1', text: @user.name
+ assert_select 'h1>img.gravatar'
+ assert_match @user.microposts.count.to_s, response.body
+ assert_select 'div.pagination'
+ @user.microposts.paginate(page: 1).each do |micropost|
+ assert_match micropost.content, response.body
+ end
+ end
+end
\ No newline at end of file
diff --git a/test/integration/users_signup_test.rb b/test/integration/users_signup_test.rb
index b17a886..f45bf95 100644
--- a/test/integration/users_signup_test.rb
+++ b/test/integration/users_signup_test.rb
@@ -1,19 +1,45 @@
require 'test_helper'
-
class UsersSignupTest < ActionDispatch::IntegrationTest
-
- # test "the truth" do
- # assert true
- # end
- test "valid signup information" do
- get signup_path
- assert_difference 'User.count', 1 do
- post_via_redirect users_path, user: { name: "Example User",
- email: "user@example.com",
- password: "password",
- password_confirmation: "password" }
+ def setup
+ ActionMailer::Base.deliveries.clear
end
- assert_template 'users/show'
- assert is_logged_in?
- end
-end
+ test "invalid signup information" do
+ get signup_path
+ assert_no_difference 'User.count' do
+ post users_path, user: { name: "",
+ email: "user@invalid",
+ password: "foo",
+ password_confirmation: "bar" }
+ end
+ assert_template 'users/new'
+ assert_select 'div#error_explanation'
+ assert_select 'div.field_with_errors'
+ end
+ test "valid signup information with account activation" do
+ get signup_path
+ assert_difference 'User.count', 1 do
+ post users_path, user: { name: "Example User",
+ email: "user@example.com",
+ password: "password",
+ password_confirmation: "password" }
+ end
+ assert_equal 1, ActionMailer::Base.deliveries.size
+ user = assigns(:user)
+ assert_not user.activated?
+ # Try to log in before activation.
+ log_in_as(user)
+ assert_not is_logged_in?
+ # Invalid activation token
+ get edit_account_activation_path("invalid token")
+ assert_not is_logged_in?
+ # Valid token, wrong email
+ get edit_account_activation_path(user.activation_token, email: 'wrong')
+ assert_not is_logged_in?
+ # Valid activation token
+ get edit_account_activation_path(user.activation_token, email: user.email)
+ assert user.reload.activated?
+ follow_redirect!
+ assert_template 'users/show'
+ assert is_logged_in?
+ end
+end
\ No newline at end of file
diff --git a/test/mailers/previews/user_mailer_preview.rb b/test/mailers/previews/user_mailer_preview.rb
new file mode 100644
index 0000000..a3a53b7
--- /dev/null
+++ b/test/mailers/previews/user_mailer_preview.rb
@@ -0,0 +1,17 @@
+# Preview all emails at http://localhost:3000/rails/mailers/user_mailer
+class UserMailerPreview < ActionMailer::Preview
+# Preview this email at
+# http://localhost:3000/rails/mailers/user_mailer/account_activation
+ def account_activation
+ user = User.first
+ user.activation_token = User.new_token
+ UserMailer.account_activation(user)
+ end
+# Preview this email at
+# http://localhost:3000/rails/mailers/user_mailer/password_reset
+ def password_reset
+ user = User.first
+ user.reset_token = User.new_token
+ UserMailer.password_reset(user)
+ end
+end
\ No newline at end of file
diff --git a/test/mailers/user_mailer_test.rb b/test/mailers/user_mailer_test.rb
new file mode 100644
index 0000000..71dcb4e
--- /dev/null
+++ b/test/mailers/user_mailer_test.rb
@@ -0,0 +1,24 @@
+require 'test_helper'
+class UserMailerTest < ActionMailer::TestCase
+ test "account_activation" do
+ user = users(:michael)
+ user.activation_token = User.new_token
+ mail = UserMailer.account_activation(user)
+ assert_equal "Account activation", mail.subject
+ assert_equal [user.email], mail.to
+ assert_equal ["noreply@example.com"], mail.from
+ assert_match user.name, mail.body.encoded
+ assert_match user.activation_token, mail.body.encoded
+ assert_match CGI::escape(user.email), mail.body.encoded
+ end
+ test "password_reset" do
+ user = users(:michael)
+ user.reset_token = User.new_token
+ mail = UserMailer.password_reset(user)
+ assert_equal "Password reset", mail.subject
+ assert_equal [user.email], mail.to
+ assert_equal ["noreply@example.com"], mail.from
+ assert_match user.reset_token, mail.body.encoded
+ assert_match CGI::escape(user.email), mail.body.encoded
+ end
+end
\ No newline at end of file
diff --git a/test/models/micropost_test.rb b/test/models/micropost_test.rb
index def8e93..dc7e172 100644
--- a/test/models/micropost_test.rb
+++ b/test/models/micropost_test.rb
@@ -4,4 +4,28 @@ class MicropostTest < ActiveSupport::TestCase
# test "the truth" do
# assert true
# end
+ def setup
+ @user = users(:michael)
+ # This code is not idiomatically correct.
+ @micropost = @user.microposts.build(content: "Lorem ipsum")
+ end
+ test "should be valid" do
+ assert @micropost.valid?
+ end
+ test "user id should be present" do
+ @micropost.user_id = nil
+ assert_not @micropost.valid?
+ end
+
+ test "content should be present " do
+ @micropost.content = " "
+ assert_not @micropost.valid?
+ end
+ test "content should be at most 140 characters" do
+ @micropost.content = "a" * 141
+ assert_not @micropost.valid?
+ end
+ test "order should be most recent first" do
+ assert_equal Micropost.first, microposts(:most_recent)
+ end
end
diff --git a/test/models/relationship_test.rb b/test/models/relationship_test.rb
new file mode 100644
index 0000000..700cc41
--- /dev/null
+++ b/test/models/relationship_test.rb
@@ -0,0 +1,7 @@
+require 'test_helper'
+
+class RelationshipTest < ActiveSupport::TestCase
+ # test "the truth" do
+ # assert true
+ # end
+end
diff --git a/test/models/user_test.rb b/test/models/user_test.rb
index 7841939..a6d832c 100644
--- a/test/models/user_test.rb
+++ b/test/models/user_test.rb
@@ -56,10 +56,10 @@ def setup
assert_equal mixed_case_email.downcase, @user.reload.email
end
- test "password should be present (nonblank)" do
- @user.password = @user.password_confirmation = " " * 6
- assert_not @user.valid?
- end
+ #test "password should be present (nonblank)" do
+ # @user.password = @user.password_confirmation = " " * 6
+ # assert_not @user.valid?
+ #end
test "password should have a minimum length" do
@user.password = @user.password_confirmation = "a" * 5
@@ -67,6 +67,42 @@ def setup
end
test "authenticated? should return false for a user with nil digest" do
- assert_not @user.authenticated?('')
+ assert_not @user.authenticated?(:remember, '')
+ end
+
+ test "associated microposts should be destroyed" do
+ @user.save
+ @user.microposts.create!(content: "Lorem ipsum")
+ assert_difference 'Micropost.count', -1 do
+ @user.destroy
+ end
+ end
+ test "should follow and unfollow a user" do
+ michael = users(:michael)
+ archer = users(:archer)
+ assert_not michael.following?(archer)
+ michael.follow(archer)
+ assert michael.following?(archer)
+ assert archer.followers.include?(michael)
+ michael.unfollow(archer)
+ assert_not michael.following?(archer)
+ end
+
+ test "feed should have the right posts" do
+ michael = users(:michael)
+ archer = users(:archer)
+ lana = users(:lana)
+ # Posts from followed user
+ lana.microposts.each do |post_following|
+ assert michael.feed.include?(post_following)
+ end
+ # Posts from self
+ michael.microposts.each do |post_self|
+ assert michael.feed.include?(post_self)
+ end
+ # Posts from unfollowed user
+ archer.microposts.each do |post_unfollowed|
+ assert_not michael.feed.include?(post_unfollowed)
+ end
end
end