Last active
October 1, 2021 15:03
-
-
Save fguillen/a3803f0a80ed33bbd8b3aa7ce732de58 to your computer and use it in GitHub Desktop.
Rails - Implementing Invitation Code mechanism
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
commit a656816e7d9498d32b52c6c9455e535466623ad9 | |
Author: Fernando | |
Date: Fri Oct 1 12:23:37 2021 +0200 | |
Invitation workflow | |
diff --git a/app/controllers/admin/invitations_controller.rb b/app/controllers/admin/invitations_controller.rb | |
new file mode 100644 | |
index 0000000..93652c0 | |
--- /dev/null | |
+++ b/app/controllers/admin/invitations_controller.rb | |
@@ -0,0 +1,53 @@ | |
+class Admin::InvitationsController < Admin::BaseController | |
+ before_action :require_admin_user | |
+ before_action :load_invitation, only: [:show, :edit, :update, :destroy] | |
+ | |
+ def index | |
+ @invitations = Invitation.order_by_recent | |
+ end | |
+ | |
+ def show; end | |
+ | |
+ def new | |
+ @invitation = Invitation.new | |
+ end | |
+ | |
+ def create | |
+ @invitation = Invitation.new(invitation_params) | |
+ | |
+ if @invitation.save | |
+ redirect_to [:admin, @invitation], notice: t("controllers.invitations.create.success") | |
+ else | |
+ flash.now[:alert] = t("controllers.invitations.create.error") | |
+ render action: :new | |
+ end | |
+ end | |
+ | |
+ def edit; end | |
+ | |
+ def update | |
+ if @invitation.update(invitation_params) | |
+ redirect_to [:admin, @invitation], notice: t("controllers.invitations.update.success") | |
+ else | |
+ flash.now[:alert] = t("controllers.invitations.update.error") | |
+ render action: :edit | |
+ end | |
+ end | |
+ | |
+ def destroy | |
+ @invitation.destroy | |
+ redirect_to :admin_invitations, notice: t("controllers.invitations.destroy.success") | |
+ end | |
+ | |
+ protected | |
+ | |
+ def invitation_params | |
+ params.require(:invitation).permit(:name) | |
+ end | |
+ | |
+ private | |
+ | |
+ def load_invitation | |
+ @invitation = Invitation.find(params[:id]) | |
+ end | |
+end | |
diff --git a/app/controllers/front/front_users_controller.rb b/app/controllers/front/front_users_controller.rb | |
index 4bd3ad3..dce2e37 100644 | |
--- a/app/controllers/front/front_users_controller.rb | |
+++ b/app/controllers/front/front_users_controller.rb | |
@@ -6,11 +6,13 @@ class Front::FrontUsersController < Front::BaseController | |
def show; end | |
def new | |
- @front_user = FrontUser.new | |
+ @front_user = FrontUser.new(invitation_id: params[:invitation_id]) | |
end | |
def create | |
@front_user = FrontUser.new(front_user_params) | |
+ @front_user.require_invitation = true | |
+ | |
if @front_user.save | |
redirect_to [:front, @front_user], notice: t("controllers.front_users.create.success") | |
else | |
@@ -57,7 +59,7 @@ class Front::FrontUsersController < Front::BaseController | |
protected | |
def front_user_params | |
- params.require(:front_user).permit(:name, :email, :password, :password_confirmation) | |
+ params.require(:front_user).permit(:name, :email, :password, :password_confirmation, :invitation_id) | |
end | |
private | |
diff --git a/app/models/front_user.rb b/app/models/front_user.rb | |
index 8013b2c..86792f8 100644 | |
--- a/app/models/front_user.rb | |
+++ b/app/models/front_user.rb | |
@@ -2,6 +2,8 @@ class FrontUser < ApplicationRecord | |
self.primary_key = :uuid | |
include HasUuid | |
+ attr_accessor :require_invitation | |
+ | |
acts_as_authentic do |config| | |
config.crypto_provider = ::Authlogic::CryptoProviders::SCrypt | |
config.session_class = FrontSession | |
@@ -10,13 +12,16 @@ class FrontUser < ApplicationRecord | |
has_many :authorizations, class_name: "FrontAuthorization", dependent: :destroy | |
has_many :posts, dependent: :destroy | |
has_many :play_gatherings, dependent: :destroy | |
+ has_one :invitation, dependent: :nullify | |
validates :name, presence: true | |
validates :email, presence: true, uniqueness: { case_sensitive: false }, format: { with: RubyRegex::Email } | |
validates :password, presence: true, on: :create | |
validates :password, confirmation: true, allow_blank: true | |
- | |
validates_with PasswordValidator, unless: -> { password.blank? } | |
+ validate :invitation_available, on: :create, if: :require_invitation? | |
+ | |
+ after_commit :use_invitation, on: :create | |
scope :order_by_recent, -> { order("created_at desc") } | |
@@ -24,4 +29,27 @@ class FrontUser < ApplicationRecord | |
reset_perishable_token! | |
Notifier.front_user_reset_password(self).deliver | |
end | |
+ | |
+ def require_invitation? | |
+ require_invitation | |
+ end | |
+ | |
+ def invitation_id | |
+ self.invitation&.uuid | |
+ end | |
+ | |
+ def invitation_id=(id) | |
+ self.invitation = Invitation.find_by(uuid: id) | |
+ end | |
+ | |
+ def invitation_available | |
+ if invitation.nil? || invitation.used? | |
+ errors.add(:invitation, "Invitation Code is not found or is already used") | |
+ end | |
+ end | |
+ | |
+ def use_invitation | |
+ return if invitation.nil? | |
+ invitation.use!(self) | |
+ end | |
end | |
diff --git a/app/models/invitation.rb b/app/models/invitation.rb | |
new file mode 100644 | |
index 0000000..dd9ed43 | |
--- /dev/null | |
+++ b/app/models/invitation.rb | |
@@ -0,0 +1,22 @@ | |
+class Invitation < ApplicationRecord | |
+ self.primary_key = :uuid | |
+ include HasUuid | |
+ | |
+ belongs_to :front_user, optional: true | |
+ | |
+ validates :name, presence: true | |
+ | |
+ scope :order_by_recent, -> { order("created_at desc") } | |
+ scope :available, -> { where(used_at: nil) } | |
+ | |
+ def used? | |
+ used_at != nil | |
+ end | |
+ | |
+ def use!(front_user) | |
+ update!( | |
+ used_at: Time.now, | |
+ front_user: front_user | |
+ ) | |
+ end | |
+end | |
diff --git a/app/views/admin/invitations/_form.html.erb b/app/views/admin/invitations/_form.html.erb | |
new file mode 100644 | |
index 0000000..5cc34d6 | |
--- /dev/null | |
+++ b/app/views/admin/invitations/_form.html.erb | |
@@ -0,0 +1,22 @@ | |
+<%= form_for [:admin, @invitation] do |f| %> | |
+ <%= render "/shared/form_errors", :object => f.object %> | |
+ | |
+ <fieldset> | |
+ <legend><%= "Invitation attributes" %></legend> | |
+ <hr> | |
+ | |
+ <div class="form-group row"> | |
+ <%= f.label :name, class: "col-sm-2 col-form-label text-right"%> | |
+ | |
+ <div class="col-sm-10"> | |
+ <%= f.text_field :name, class: "form-control", placeholder: t("activerecord.attributes.invitation.name") %> | |
+ </div> | |
+ </div> | |
+ | |
+ <div class="form-group row"> | |
+ <div class="offset-sm-2 col-sm-10"> | |
+ <%= f.submit class: "btn btn-primary" %> | |
+ </div> | |
+ </div> | |
+ </fieldset> | |
+<% end %> | |
diff --git a/app/views/admin/invitations/_list.html.erb b/app/views/admin/invitations/_list.html.erb | |
new file mode 100644 | |
index 0000000..814fb22 | |
--- /dev/null | |
+++ b/app/views/admin/invitations/_list.html.erb | |
@@ -0,0 +1,19 @@ | |
+<table class="table table-striped table-hover"> | |
+ <tr> | |
+ <th><%= t "activerecord.attributes.invitation.uuid" %></th> | |
+ <th><%= t "activerecord.attributes.invitation.name" %></th> | |
+ <th><%= t "activerecord.attributes.invitation.created_at" %></th> | |
+ <th><%= t "activerecord.attributes.invitation.used_at" %></th> | |
+ <th><%= t "activerecord.attributes.invitation.front_user.name" %></th> | |
+ </tr> | |
+ | |
+ <% invitations.each do |invitation| %> | |
+ <tr> | |
+ <td><%= link_to invitation.uuid, [:admin, invitation] %></td> | |
+ <td><%= invitation.name %></td> | |
+ <td><%= invitation.created_at.to_s(:datetimedb) %></td> | |
+ <td><%= invitation.used_at ? invitation.used_at.to_s(:datetimedb) : "-" %></td> | |
+ <td><%= invitation.front_user ? link_to(invitation.front_user.name, [:admin, invitation.front_user]) : "-" %></td> | |
+ </tr> | |
+ <% end %> | |
+</table> | |
diff --git a/app/views/admin/invitations/edit.html.erb b/app/views/admin/invitations/edit.html.erb | |
new file mode 100644 | |
index 0000000..6c77233 | |
--- /dev/null | |
+++ b/app/views/admin/invitations/edit.html.erb | |
@@ -0,0 +1,13 @@ | |
+<% title t("views.invitations.edit.title", :invitation_uuid => @invitation.uuid) %> | |
+ | |
+<ol class="breadcrumb"> | |
+ <li class="breadcrumb-item"><%= link_to t("layouts.breadcrumbs.invitations"), :admin_invitations %></li> | |
+ <li class="breadcrumb-item"><%= link_to @invitation.uuid, [:admin, @invitation] %></li> | |
+ <li class="breadcrumb-item active"><%= t "layouts.breadcrumbs.edit" %></li> | |
+</ol> | |
+ | |
+<p class="lead"> | |
+ <%= t "views.invitations.edit.text" %> | |
+</p> | |
+ | |
+<%= render "form" %> | |
diff --git a/app/views/admin/invitations/index.html.erb b/app/views/admin/invitations/index.html.erb | |
new file mode 100644 | |
index 0000000..2068f02 | |
--- /dev/null | |
+++ b/app/views/admin/invitations/index.html.erb | |
@@ -0,0 +1,11 @@ | |
+<% title t("views.invitations.index.title") %> | |
+ | |
+<nav aria-label="breadcrumb"> | |
+ <ol class="breadcrumb"> | |
+ <li class="breadcrumb-item active"><%= t "layouts.breadcrumbs.invitations" %></li> | |
+ </ol> | |
+</nav> | |
+ | |
+<p><%= link_to "New Invitation", new_admin_invitation_path, :class => "btn btn-outline-primary" %></p> | |
+ | |
+<%= render partial: "list", locals: { invitations: @invitations } %> | |
diff --git a/app/views/admin/invitations/new.html.erb b/app/views/admin/invitations/new.html.erb | |
new file mode 100644 | |
index 0000000..448dc0e | |
--- /dev/null | |
+++ b/app/views/admin/invitations/new.html.erb | |
@@ -0,0 +1,15 @@ | |
+<% title t("views.invitations.new.title") %> | |
+ | |
+<nav aria-label="breadcrumb"> | |
+ <ol class="breadcrumb"> | |
+ <li class="breadcrumb-item"><%= link_to t("layouts.breadcrumbs.invitations"), :admin_invitations %></li> | |
+ <li class="breadcrumb-item active"><%= t "layouts.breadcrumbs.new" %></li> | |
+ </ol> | |
+</nav> | |
+ | |
+<p class="lead"> | |
+ <%= t("views.invitations.new.text") %> | |
+</p> | |
+ | |
+ | |
+<%= render "form" %> | |
diff --git a/app/views/admin/invitations/show.html.erb b/app/views/admin/invitations/show.html.erb | |
new file mode 100644 | |
index 0000000..2ea8de3 | |
--- /dev/null | |
+++ b/app/views/admin/invitations/show.html.erb | |
@@ -0,0 +1,24 @@ | |
+<% title t("views.invitations.show.title", :invitation_uuid => @invitation.uuid) %> | |
+ | |
+<nav aria-label="breadcrumb"> | |
+ <ol class="breadcrumb"> | |
+ <li class="breadcrumb-item"><%= link_to t("layouts.breadcrumbs.invitations"), :admin_invitations %></li> | |
+ <li class="breadcrumb-item active"><%= @invitation.uuid %></li> | |
+ </ol> | |
+</nav> | |
+ | |
+<dl class="row"> | |
+ <dt class="col-sm-2 text-right"><%= t "activerecord.attributes.invitation.uuid" %></dt><dd class="col-sm-10"><%= @invitation.uuid %></dd> | |
+ <dt class="col-sm-2 text-right"><%= t "activerecord.attributes.invitation.name" %></dt><dd class="col-sm-10"><%= @invitation.name %></dd> | |
+ <dt class="col-sm-2 text-right"><%= t "activerecord.attributes.invitation.created_at" %></dt><dd class="col-sm-10"><%= @invitation.created_at.to_s(:datetimedb) %></dd> | |
+ <dt class="col-sm-2 text-right"><%= t "activerecord.attributes.invitation.used_at" %></dt><dd class="col-sm-10"><%= @invitation.used_at ? @invitation.used_at.to_s(:datetimedb) : "-" %></dd> | |
+ <dt class="col-sm-2 text-right"><%= t "activerecord.attributes.invitation.front_user.name" %></dt><dd class="col-sm-10"><%= @invitation.front_user ? link_to(@invitation.front_user.name, [:admin, @invitation.front_user]) : "-" %></dd> | |
+ <dt class="col-sm-2 text-right"><%= t "activerecord.attributes.invitation.link" %></dt><dd class="col-sm-10"><%= link_to new_front_front_user_url(invitation_id: @invitation), new_front_front_user_url(invitation_id: @invitation), target: "_blank" %></dd> | |
+</dl> | |
+ | |
+<div class="controls text-right"> | |
+ <p> | |
+ <%= link_to t("views.invitations.show.edit_button"), edit_admin_invitation_path(@invitation), :class => "btn btn-primary" %> | |
+ <%= link_to t("views.invitations.show.delete_button"), [:admin, @invitation], :data => { :confirm => t("views.invitations.show.delete_confirmation") }, :method => :delete, :class => "btn btn-danger" %> | |
+ </p> | |
+</div> | |
diff --git a/app/views/front/front_users/_form.html.erb b/app/views/front/front_users/_form.html.erb | |
index 8ded723..5ce08fd 100644 | |
--- a/app/views/front/front_users/_form.html.erb | |
+++ b/app/views/front/front_users/_form.html.erb | |
@@ -4,6 +4,14 @@ | |
<legend><%= "FrontUser attributes" %></legend> | |
<hr> | |
+ <div class="row mb-3"> | |
+ <%= f.label :invitation_id, class: "col-sm-2 col-form-label text-end"%> | |
+ <div class="col-sm-10"> | |
+ <%= f.text_field :invitation_id, class: "form-control", placeholder: t("activerecord.attributes.front_user.invitation_id") %> | |
+ <div class="form-text">Introduce the Invitation Code.</div> | |
+ </div> | |
+ </div> | |
+ | |
<div class="row mb-3"> | |
<%= f.label :name, class: "col-sm-2 col-form-label text-end"%> | |
<div class="col-sm-10"> | |
diff --git a/app/views/layouts/admin/_menu.html.erb b/app/views/layouts/admin/_menu.html.erb | |
index 261266d..4942387 100644 | |
--- a/app/views/layouts/admin/_menu.html.erb | |
+++ b/app/views/layouts/admin/_menu.html.erb | |
@@ -8,6 +8,7 @@ | |
<li class="nav-item"><%= link_to t("layouts.menu.admin_users"), :admin_admin_users, class: "nav-link" %></li> | |
<li class="nav-item"><%= link_to t("layouts.menu.front_users"), :admin_front_users, class: "nav-link" %></li> | |
<li class="nav-item"><%= link_to t("layouts.menu.posts"), :admin_posts, class: "nav-link" %></li> | |
+ <li class="nav-item"><%= link_to t("layouts.menu.invitations"), :admin_invitations, class: "nav-link" %></li> | |
<li class="nav-item dropdown"> | |
<a class="nav-link dropdown-toggle" data-bs-toggle="dropdown" href="#" role="button" aria-expanded="false"><%= current_admin_user.name %></a> | |
diff --git a/config/locales/custom/en.yml b/config/locales/custom/en.yml | |
index b9ac28e..0a70967 100644 | |
--- a/config/locales/custom/en.yml | |
+++ b/config/locales/custom/en.yml | |
@@ -15,11 +15,20 @@ en: | |
front_user: | |
created_at: Created at | |
email: Email | |
+ invitation_id: Invitation | |
name: Name | |
one: FrontUser | |
password: Password | |
password_confirmation: Password confirmation | |
uuid: Uuid | |
+ invitation: | |
+ created_at: Created at | |
+ front_user: | |
+ name: Name | |
+ link: Link | |
+ name: Name | |
+ used_at: Used at | |
+ uuid: Uuid | |
play_gathering: | |
description: Description | |
title: Title | |
@@ -85,6 +94,15 @@ en: | |
update: | |
error: Errors were encountered when trying to update Front User | |
success: Successfully updated Front User | |
+ invitations: | |
+ create: | |
+ error: Error | |
+ success: Success | |
+ destroy: | |
+ success: Success | |
+ update: | |
+ error: Error | |
+ success: Success | |
play_gatherings: | |
create: | |
error: Error | |
@@ -114,6 +132,7 @@ en: | |
forgot_password: Forgotten Password | |
front_sessions: Front sessions | |
front_users: Front users | |
+ invitations: Invitations | |
login_admin: Admin Login | |
login_front: Login front | |
new: New | |
@@ -127,6 +146,7 @@ en: | |
features: Features | |
front_users: Front users | |
home: Home | |
+ invitations: Invitations | |
login: Login | |
logout: Logout | |
my_posts: See my posts | |
@@ -191,6 +211,20 @@ en: | |
delete_confirmation: Delete confirmation | |
edit_button: Edit button | |
title: Title | |
+ invitations: | |
+ edit: | |
+ text: Text | |
+ title: Title | |
+ index: | |
+ title: Title | |
+ new: | |
+ text: Text | |
+ title: Title | |
+ show: | |
+ delete_button: Delete button | |
+ delete_confirmation: Delete confirmation | |
+ edit_button: Edit button | |
+ title: Title | |
play_gathering: | |
sections: | |
play_sessions: Play sessions | |
diff --git a/config/routes.rb b/config/routes.rb | |
index 4e561c1..ef80c10 100644 | |
--- a/config/routes.rb | |
+++ b/config/routes.rb | |
@@ -17,6 +17,7 @@ Rails.application.routes.draw do | |
get "posts", on: :member | |
end | |
resources :posts | |
+ resources :invitations | |
end | |
namespace :api do | |
diff --git a/db/migrate/20211001100637_create_invitations.rb b/db/migrate/20211001100637_create_invitations.rb | |
new file mode 100644 | |
index 0000000..e4fb931 | |
--- /dev/null | |
+++ b/db/migrate/20211001100637_create_invitations.rb | |
@@ -0,0 +1,14 @@ | |
+class CreateInvitations < ActiveRecord::Migration[6.1] | |
+ def change | |
+ create_table :invitations, id: false, force: true do |t| | |
+ t.string :uuid, null: false, limit: 36, index: { unique: true }, primary_key: true | |
+ t.string :name, null: false | |
+ t.string :front_user_id, limit: 36 | |
+ t.datetime :used_at | |
+ | |
+ t.timestamps | |
+ end | |
+ | |
+ add_foreign_key :invitations, :front_users, column: :front_user_id, primary_key: "uuid" | |
+ end | |
+end | |
diff --git a/db/schema.rb b/db/schema.rb | |
index 12575ab..f57ae05 100644 | |
--- a/db/schema.rb | |
+++ b/db/schema.rb | |
@@ -10,7 +10,7 @@ | |
# | |
# It's strongly recommended that you check this file into your version control system. | |
-ActiveRecord::Schema.define(version: 2021_09_30_161442) do | |
+ActiveRecord::Schema.define(version: 2021_10_01_100637) do | |
create_table "active_storage_attachments", charset: "utf8mb4", collation: "utf8mb4_bin", force: :cascade do |t| | |
t.string "name", null: false | |
@@ -85,6 +85,16 @@ ActiveRecord::Schema.define(version: 2021_09_30_161442) do | |
t.index ["uuid"], name: "index_front_users_on_uuid", unique: true | |
end | |
+ create_table "invitations", primary_key: "uuid", id: { type: :string, limit: 36 }, charset: "utf8mb4", collation: "utf8mb4_bin", force: :cascade do |t| | |
+ t.string "name", null: false | |
+ t.string "front_user_id", limit: 36 | |
+ t.datetime "used_at" | |
+ t.datetime "created_at", precision: 6, null: false | |
+ t.datetime "updated_at", precision: 6, null: false | |
+ t.index ["front_user_id"], name: "fk_rails_415b8ee2dd" | |
+ t.index ["uuid"], name: "index_invitations_on_uuid", unique: true | |
+ end | |
+ | |
create_table "play_gatherings", primary_key: "uuid", id: { type: :string, limit: 36 }, charset: "utf8mb4", collation: "utf8mb4_bin", force: :cascade do |t| | |
t.string "title", null: false | |
t.text "description", null: false | |
@@ -164,6 +174,7 @@ ActiveRecord::Schema.define(version: 2021_09_30_161442) do | |
add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id" | |
add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_id" | |
+ add_foreign_key "invitations", "front_users", primary_key: "uuid" | |
add_foreign_key "play_gatherings", "front_users", primary_key: "uuid" | |
add_foreign_key "play_sessions", "play_gatherings", primary_key: "uuid" | |
add_foreign_key "posts", "front_users", primary_key: "uuid" | |
diff --git a/test/controllers/admin/invitations_controller_test.rb b/test/controllers/admin/invitations_controller_test.rb | |
new file mode 100644 | |
index 0000000..20dec78 | |
--- /dev/null | |
+++ b/test/controllers/admin/invitations_controller_test.rb | |
@@ -0,0 +1,127 @@ | |
+require "test_helper" | |
+ | |
+class Admin::InvitationsControllerTest < ActionController::TestCase | |
+ def setup | |
+ setup_admin_user | |
+ end | |
+ | |
+ def test_index | |
+ invitation_1 = FactoryBot.create(:invitation, created_at: "2020-04-25") | |
+ invitation_2 = FactoryBot.create(:invitation, created_at: "2020-04-26") | |
+ | |
+ get :index | |
+ | |
+ assert_template "admin/invitations/index" | |
+ assert_primary_keys([invitation_2, invitation_1], assigns(:invitations)) | |
+ end | |
+ | |
+ def test_show | |
+ invitation = FactoryBot.create(:invitation) | |
+ | |
+ get :show, params: { id: invitation } | |
+ | |
+ assert_template "admin/invitations/show" | |
+ assert_equal(invitation, assigns(:invitation)) | |
+ end | |
+ | |
+ def test_new | |
+ get :new | |
+ assert_template "admin/invitations/new" | |
+ assert_not_nil(assigns(:invitation)) | |
+ end | |
+ | |
+ def test_create_invalid | |
+ front_user_1 = FactoryBot.create(:front_user) | |
+ | |
+ Invitation.any_instance.stubs(:valid?).returns(false) | |
+ | |
+ post( | |
+ :create, | |
+ params: { | |
+ invitation: { | |
+ name: "INVITATION_NAME" | |
+ } | |
+ } | |
+ ) | |
+ | |
+ assert_template "new" | |
+ assert_not_nil(flash[:alert]) | |
+ end | |
+ | |
+ def test_create_valid | |
+ front_user_1 = FactoryBot.create(:front_user) | |
+ | |
+ post( | |
+ :create, | |
+ params: { | |
+ invitation: { | |
+ name: "INVITATION_NAME" | |
+ } | |
+ } | |
+ ) | |
+ | |
+ invitation = Invitation.last | |
+ assert_redirected_to [:admin, invitation] | |
+ | |
+ assert_equal("INVITATION_NAME", invitation.name) | |
+ end | |
+ | |
+ def test_edit | |
+ invitation = FactoryBot.create(:invitation) | |
+ | |
+ get :edit, params: { id: invitation } | |
+ | |
+ assert_template "edit" | |
+ assert_equal(invitation, assigns(:invitation)) | |
+ end | |
+ | |
+ def test_update_invalid | |
+ invitation = FactoryBot.create(:invitation) | |
+ | |
+ Invitation.any_instance.stubs(:valid?).returns(false) | |
+ | |
+ put( | |
+ :update, | |
+ params: { | |
+ id: invitation, | |
+ invitation: { | |
+ name: "THE_NEW_NAME" | |
+ } | |
+ } | |
+ ) | |
+ | |
+ assert_template "edit" | |
+ assert_not_nil(flash[:alert]) | |
+ end | |
+ | |
+ def test_update_valid | |
+ invitation = FactoryBot.create(:invitation) | |
+ | |
+ put( | |
+ :update, | |
+ params: { | |
+ id: invitation, | |
+ invitation: { | |
+ name: "THE_NEW_NAME" | |
+ } | |
+ } | |
+ ) | |
+ | |
+ assert_redirected_to [:admin, invitation] | |
+ assert_not_nil(flash[:notice]) | |
+ | |
+ invitation.reload | |
+ assert_equal("THE_NEW_NAME", invitation.name) | |
+ end | |
+ | |
+ def test_destroy | |
+ invitation = FactoryBot.create(:invitation) | |
+ | |
+ delete :destroy, params: { id: invitation } | |
+ | |
+ assert_redirected_to :admin_invitations | |
+ assert_not_nil(flash[:notice]) | |
+ | |
+ assert !Invitation.exists?(invitation.id) | |
+ end | |
+end | |
diff --git a/test/controllers/front/front_users_controller_test.rb b/test/controllers/front/front_users_controller_test.rb | |
index 048ea14..78459f6 100644 | |
--- a/test/controllers/front/front_users_controller_test.rb | |
+++ b/test/controllers/front/front_users_controller_test.rb | |
@@ -37,7 +37,28 @@ class Front::FrontUsersControllerTest < ActionController::TestCase | |
assert_not_nil(flash[:alert]) | |
end | |
+ def test_create_without_valid_invitation | |
+ assert_difference("FrontUser.count", 0) do | |
+ post( | |
+ :create, | |
+ params: { | |
+ front_user: { | |
+ name: "Front Wadus", | |
+ email: "email@email.com", | |
+ password: "Password!", | |
+ password_confirmation: "Password!" | |
+ } | |
+ } | |
+ ) | |
+ end | |
+ | |
+ assert_template "new" | |
+ assert_not_nil(flash[:alert]) | |
+ end | |
+ | |
def test_create_valid | |
+ invitation = FactoryBot.create(:invitation) | |
+ | |
post( | |
:create, | |
params: { | |
@@ -45,7 +66,8 @@ class Front::FrontUsersControllerTest < ActionController::TestCase | |
name: "Front Wadus", | |
email: "email@email.com", | |
password: "Password!", | |
- password_confirmation: "Password!" | |
+ password_confirmation: "Password!", | |
+ invitation_id: invitation | |
} | |
} | |
) | |
@@ -55,6 +77,11 @@ class Front::FrontUsersControllerTest < ActionController::TestCase | |
assert_equal("Front Wadus", front_user.name) | |
assert_equal("email@email.com", front_user.email) | |
+ assert_equal(invitation, front_user.invitation) | |
+ | |
+ invitation.reload | |
+ assert(invitation.used?) | |
+ assert_equal(front_user, invitation.front_user) | |
end | |
def test_edit | |
diff --git a/test/factories.rb b/test/factories.rb | |
index f2d94da..f46b531 100644 | |
--- a/test/factories.rb | |
+++ b/test/factories.rb | |
@@ -38,4 +38,8 @@ FactoryBot.define do | |
factory :play_session do | |
play_gathering | |
end | |
+ | |
+ factory :invitation do | |
+ name { Faker::Lorem.sentence(word_count: 3) } | |
+ end | |
end | |
diff --git a/test/models/front_user_test.rb b/test/models/front_user_test.rb | |
index 35430ce..194444a 100644 | |
--- a/test/models/front_user_test.rb | |
+++ b/test/models/front_user_test.rb | |
@@ -27,4 +27,28 @@ class FrontUserTest < ActiveSupport::TestCase | |
assert_primary_keys([front_user_3, front_user_2, front_user_1], FrontUser.order_by_recent) | |
end | |
+ | |
+ # Invitation :: INI | |
+ def test_on_create_no_fail_if_no_invitation_but_invitation_no_required | |
+ front_user = FactoryBot.create(:front_user, invitation_id: nil, require_invitation: false) | |
+ assert front_user.valid? | |
+ end | |
+ | |
+ def test_on_create_fail_if_no_invitation | |
+ front_user = FactoryBot.build(:front_user, invitation_id: nil, require_invitation: true) | |
+ refute front_user.valid? | |
+ end | |
+ | |
+ def test_on_create_fail_if_used_invitation | |
+ invitation = FactoryBot.create(:invitation, used_at: Time.now) | |
+ front_user = FactoryBot.build(:front_user, invitation_id: invitation, require_invitation: true) | |
+ refute front_user.valid? | |
+ end | |
+ | |
+ def test_on_create_with_proper_invitation | |
+ invitation = FactoryBot.create(:invitation) | |
+ front_user = FactoryBot.create(:front_user, invitation_id: invitation, require_invitation: true) | |
+ assert front_user.valid? | |
+ end | |
+ # Invitation :: END | |
end | |
diff --git a/test/models/invitation_test.rb b/test/models/invitation_test.rb | |
new file mode 100644 | |
index 0000000..8bb1c0f | |
--- /dev/null | |
+++ b/test/models/invitation_test.rb | |
@@ -0,0 +1,59 @@ | |
+require "test_helper" | |
+ | |
+class InvitationTest < ActiveSupport::TestCase | |
+ def test_fixture_is_valid | |
+ assert FactoryBot.create(:invitation).valid? | |
+ end | |
+ | |
+ def test_validations | |
+ invitation = FactoryBot.build(:invitation) | |
+ assert(invitation.valid?) | |
+ | |
+ invitation = FactoryBot.build(:invitation, name: nil) | |
+ refute(invitation.valid?) | |
+ | |
+ invitation = FactoryBot.build(:invitation, front_user: nil) | |
+ assert(invitation.valid?) | |
+ end | |
+ | |
+ def test_uuid_on_create | |
+ invitation = FactoryBot.build(:invitation) | |
+ assert_nil(invitation.uuid) | |
+ | |
+ invitation.save! | |
+ | |
+ assert_not_nil(invitation.uuid) | |
+ end | |
+ | |
+ def test_primary_key | |
+ invitation = FactoryBot.create(:invitation) | |
+ | |
+ assert_equal(invitation, Invitation.find(invitation.uuid)) | |
+ end | |
+ | |
+ def test_relations | |
+ front_user = FactoryBot.create(:front_user) | |
+ | |
+ invitation = FactoryBot.create(:invitation, front_user: front_user) | |
+ | |
+ assert_equal(front_user, invitation.front_user) | |
+ end | |
+ | |
+ def test_used | |
+ invitation = FactoryBot.create(:invitation) | |
+ refute invitation.used? | |
+ | |
+ invitation.used_at = Time.now | |
+ assert invitation.used? | |
+ end | |
+ | |
+ def test_use | |
+ front_user = FactoryBot.create(:front_user) | |
+ invitation = FactoryBot.create(:invitation) | |
+ refute invitation.used? | |
+ | |
+ invitation.use!(front_user) | |
+ assert invitation.used? | |
+ assert_equal(front_user, invitation.front_user) | |
+ end | |
+end | |
diff --git a/test/models/post_test copy.rb b/test/models/post_test copy.rb | |
new file mode 100644 | |
index 0000000..4458980 | |
--- /dev/null | |
+++ b/test/models/post_test copy.rb | |
@@ -0,0 +1,71 @@ | |
+require "test_helper" | |
+ | |
+class PostTest < ActiveSupport::TestCase | |
+ def test_fixture_is_valid | |
+ assert FactoryBot.create(:post).valid? | |
+ end | |
+ | |
+ def test_validations | |
+ post = FactoryBot.build(:post) | |
+ assert(post.valid?) | |
+ | |
+ post = FactoryBot.build(:post, title: nil) | |
+ refute(post.valid?) | |
+ | |
+ post = FactoryBot.build(:post, body: nil) | |
+ refute(post.valid?) | |
+ | |
+ post = FactoryBot.build(:post, body: "") | |
+ refute(post.valid?) | |
+ | |
+ post = FactoryBot.build(:post, body: "A" * 6) | |
+ refute(post.valid?) | |
+ | |
+ post = FactoryBot.build(:post, body: "A" * 65_536) | |
+ refute(post.valid?) | |
+ | |
+ post = FactoryBot.build(:post, body: "A" * 30) | |
+ assert(post.valid?) | |
+ | |
+ post = FactoryBot.build(:post, front_user: nil) | |
+ refute(post.valid?) | |
+ end | |
+ | |
+ def test_uuid_on_create | |
+ post = FactoryBot.build(:post) | |
+ assert_nil(post.uuid) | |
+ | |
+ post.save! | |
+ | |
+ assert_not_nil(post.uuid) | |
+ end | |
+ | |
+ def test_primary_key | |
+ post = FactoryBot.create(:post) | |
+ | |
+ assert_equal(post, Post.find(post.uuid)) | |
+ end | |
+ | |
+ def test_relations | |
+ front_user = FactoryBot.create(:front_user) | |
+ | |
+ post = FactoryBot.create(:post, front_user: front_user) | |
+ | |
+ assert_equal(front_user, post.front_user) | |
+ end | |
+ | |
+ def test_tags | |
+ post = FactoryBot.create(:post, tag_list: ["one", "two"]) | |
+ assert_equal(2, post.tags.count) | |
+ assert_equal(["one", "two"], post.tag_list) | |
+ assert_equal(["one", "two"], post.tags.map(&:name)) | |
+ | |
+ post = FactoryBot.create(:post, tag_list: "one, two") | |
+ assert_equal(2, post.tags.count) | |
+ assert_equal(["one", "two"], post.tag_list) | |
+ assert_equal(["one", "two"], post.tags.map(&:name)) | |
+ | |
+ post = FactoryBot.create(:post, tag_list: "One, Two") | |
+ assert_equal(["one", "two"], post.tag_list) | |
+ end | |
+end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment