diff --git a/.gitignore b/.gitignore index e38a997..bc8e397 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,7 @@ /tmp coverage .env + +.byebug_history + +*.lock diff --git a/.rubocop.yml b/.rubocop.yml index 7881188..ba12389 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -4,5 +4,5 @@ Documentation: AllCops: RunRailsCops: true Exclude: - - db/** - - config/** + - db/**/* + - config/**/* diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..3d52269 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,4 @@ +language: ruby +rvm: + - 2.2.3 +sudo: false diff --git a/Gemfile b/Gemfile index 11bdaf2..041e4c0 100644 --- a/Gemfile +++ b/Gemfile @@ -2,6 +2,7 @@ source 'https://rubygems.org' ruby '2.2.3' gem 'rails', '4.2.5' +gem 'bootstrap_form' gem 'devise' gem 'http_logger' gem 'jquery-rails' diff --git a/Gemfile.lock b/Gemfile.lock index 0c46029..81efd61 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -47,6 +47,7 @@ GEM bcrypt (3.1.10) binding_of_caller (0.7.2) debug_inspector (>= 0.0.1) + bootstrap_form (2.3.0) builder (3.2.2) byebug (8.2.0) capybara (2.5.0) @@ -251,6 +252,7 @@ PLATFORMS DEPENDENCIES annotate + bootstrap_form byebug coveralls devise diff --git a/README.md b/README.md new file mode 100644 index 0000000..54b3c6b --- /dev/null +++ b/README.md @@ -0,0 +1,9 @@ +# QuickSubmit + +[![Build Status](https://travis-ci.org/MITLibraries/QuickSubmit.svg)](https://travis-ci.org/MITLibraries/QuickSubmit) +[![Dependency Status](https://gemnasium.com/MITLibraries/QuickSubmit.svg)](https://gemnasium.com/MITLibraries/QuickSubmit) +[![Code Climate](https://codeclimate.com/github/MITLibraries/QuickSubmit/badges/gpa.svg)](https://codeclimate.com/github/MITLibraries/QuickSubmit) + +## What is this? + +QuickSubmit will be a brief form where users can upload an article along with sparse metadata. This will be transformed into METS and then SWORD and submitted to an Institutional Repository (DSpace for now). diff --git a/README.rdoc b/README.rdoc deleted file mode 100644 index dd4e97e..0000000 --- a/README.rdoc +++ /dev/null @@ -1,28 +0,0 @@ -== README - -This README would normally document whatever steps are necessary to get the -application up and running. - -Things you may want to cover: - -* Ruby version - -* System dependencies - -* Configuration - -* Database creation - -* Database initialization - -* How to run the test suite - -* Services (job queues, cache servers, search engines, etc.) - -* Deployment instructions - -* ... - - -Please feel free to use a different markup language if you do not plan to run -rake doc:app. diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index f9cd5b3..01154bc 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -12,4 +12,5 @@ * *= require_tree . *= require_self + *= require rails_bootstrap_forms */ diff --git a/app/assets/stylesheets/submission.css b/app/assets/stylesheets/submission.css new file mode 100644 index 0000000..88a1e09 --- /dev/null +++ b/app/assets/stylesheets/submission.css @@ -0,0 +1,3 @@ +label.required:after { + content:" *"; +} diff --git a/app/controllers/submissions_controller.rb b/app/controllers/submissions_controller.rb new file mode 100644 index 0000000..3db53b3 --- /dev/null +++ b/app/controllers/submissions_controller.rb @@ -0,0 +1,26 @@ +class SubmissionsController < ApplicationController + before_action :authenticate_user! + + def new + @submission = Submission.new + @submission.user = current_user + end + + def create + @submission = Submission.new(submission_params) + @submission.user = current_user + if @submission.save + flash.notice = 'Your Submission is now in progress.' + redirect_to root_path + else + render 'new' + end + end + + private + + def submission_params + params.require(:submission).permit(:title, :agreed_to_license, :author, + :journal, :doi, :grant_number, :doe) + end +end diff --git a/app/models/submission.rb b/app/models/submission.rb new file mode 100644 index 0000000..25b5ace --- /dev/null +++ b/app/models/submission.rb @@ -0,0 +1,23 @@ +# == Schema Information +# +# Table name: submissions +# +# id :integer not null, primary key +# user_id :integer +# title :string not null +# journal :string +# doi :string +# author :string +# doe :boolean +# grant_number :string +# agreed_to_license :boolean +# created_at :datetime not null +# updated_at :datetime not null +# + +class Submission < ActiveRecord::Base + belongs_to :user + validates :user, presence: true + validates :title, presence: true + validates :agreed_to_license, inclusion: { in: [true] } +end diff --git a/app/models/user.rb b/app/models/user.rb index 44fd3a9..fdc0b96 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -11,6 +11,7 @@ class User < ActiveRecord::Base devise :omniauthable, omniauth_providers: [:mit_oauth2] + has_many :submissions def self.from_omniauth(auth) where(uid: auth.uid).first_or_create do |user| diff --git a/app/views/submissions/new.html.erb b/app/views/submissions/new.html.erb new file mode 100644 index 0000000..ec132ae --- /dev/null +++ b/app/views/submissions/new.html.erb @@ -0,0 +1,23 @@ +

MIT DSpace Quick Submit

+ +<%= bootstrap_form_for(@submission, layout: :horizontal, label_col: "col-sm-2", control_col: "col-sm-10") do |f| %> + <%= f.alert_message "Please fix the errors below." %> + <%= f.text_field :author %> + <%= f.text_field :title %> + <%= f.text_field :journal %> + <%= f.text_field :doi %> + <%= f.text_field :grant_number %> + + <%= f.form_group :doe do %> + <%= f.check_box :doe, label: "This submission was funded in part by grants from the DOE." %> + <% end %> + + <%= f.form_group :agreed_to_license do %> + <%= f.check_box :agreed_to_license, + label: "I am authorized to submit this article." %> + <% end %> + + <%= f.form_group do %> + <%= f.submit %> + <% end %> +<% end %> diff --git a/config/routes.rb b/config/routes.rb index f011ee0..1d64e32 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,10 +1,12 @@ Rails.application.routes.draw do + resources :submissions, only: [:new, :create] + devise_for :users, :controllers => { :omniauth_callbacks => 'users/omniauth_callbacks' } devise_scope :user do - get 'sign_in', to: 'devise/sessions#new', as: :new_user_session + get 'sign_in', to: 'devise/sessions#new', as: :user_session delete 'sign_out', to: 'devise/sessions#destroy', as: :destroy_user_session end diff --git a/db/migrate/20151116184904_create_submissions.rb b/db/migrate/20151116184904_create_submissions.rb new file mode 100644 index 0000000..6074429 --- /dev/null +++ b/db/migrate/20151116184904_create_submissions.rb @@ -0,0 +1,17 @@ +class CreateSubmissions < ActiveRecord::Migration + def change + create_table :submissions do |t| + t.belongs_to :user, index: true + + t.string :title, null: false + t.string :journal + t.string :doi + t.string :author + t.boolean :doe + t.string :grant_number + t.boolean :agreed_to_license + + t.timestamps null: false + end + end +end diff --git a/db/schema.rb b/db/schema.rb index f719470..ae625f0 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,22 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20150101010101) do +ActiveRecord::Schema.define(version: 20151116184904) do + + create_table "submissions", force: :cascade do |t| + t.integer "user_id" + t.string "title", null: false + t.string "journal" + t.string "doi" + t.string "author" + t.boolean "doe" + t.string "grant_number" + t.boolean "agreed_to_license" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + + add_index "submissions", ["user_id"], name: "index_submissions_on_user_id" create_table "users", force: :cascade do |t| t.string "email", null: false diff --git a/test/controllers/submissions_controller_test.rb b/test/controllers/submissions_controller_test.rb new file mode 100644 index 0000000..52e7dd7 --- /dev/null +++ b/test/controllers/submissions_controller_test.rb @@ -0,0 +1,25 @@ +require 'test_helper' + +class SubmissionsControllerTest < ActionController::TestCase + test 'non signed in user should redirect to login requesting new' do + get :new + assert_response :redirect + end + + test 'signed in user should get new' do + sign_in users(:one) + get :new + assert_response :success + end + + test 'non signed in user should redirect to login posting to create' do + post :create + assert_response :redirect + end + + test 'signed in user can post to create' do + sign_in users(:one) + post :create, submission: { 'title': '' } + assert_response :success + end +end diff --git a/test/features/static_test.rb b/test/features/static_test.rb index fbc6483..560f652 100644 --- a/test/features/static_test.rb +++ b/test/features/static_test.rb @@ -15,8 +15,8 @@ def teardown test 'sign in link' do visit root_path - assert page.has_link?('Sign in') - refute page.has_link?('Sign out') + assert_link('Sign in') + refute_link('Sign out') end test 'sign out link' do @@ -27,7 +27,7 @@ def teardown visit '/users/auth/mit_oauth2/callback' visit root_path - assert page.has_link?('Sign out') - refute page.has_link?('Sign in') + assert_link('Sign out') + refute_link('Sign in') end end diff --git a/test/features/submission_test.rb b/test/features/submission_test.rb new file mode 100644 index 0000000..3b55163 --- /dev/null +++ b/test/features/submission_test.rb @@ -0,0 +1,70 @@ +require 'test_helper' + +class SubmissionPagesTest < Capybara::Rails::TestCase + def setup + Rails.application.env_config['devise.mapping'] = Devise.mappings[:user] + Rails.application.env_config['omniauth.auth'] = + OmniAuth.config.mock_auth[:mit_oauth2] + OmniAuth.config.test_mode = true + end + + def teardown + OmniAuth.config.test_mode = false + OmniAuth.config.mock_auth[:mit_oauth2] = nil + end + + def mock_auth + OmniAuth.config.mock_auth[:mit_oauth2] = + OmniAuth::AuthHash.new(provider: 'mit_oauth2', + uid: '123545', + info: { email: 'bob@asdf.com' }) + visit '/users/auth/mit_oauth2/callback' + end + + test 'requires signed_in user' do + visit new_submission_path + assert_equal(root_path, current_path) + assert_text('Sign in') + assert_text('You need to sign in or sign up before continuing.') + end + + test 'authenticated users can view the form' do + mock_auth + visit new_submission_path + assert_equal(new_submission_path, current_path) + end + + test 'invalid form retains valid portions' do + mock_auth + visit new_submission_path + fill_in('Journal', with: 'Super Mega Journal') + click_on('Create Submission') + assert_text('Please fix the errors below') + assert_text("Title can't be blank") + assert_text('Agreed to license is not included in the list') + assert_selector("input[value='Super Mega Journal']") + end + + test 'invalid form submit does not create new submissions' do + mock_auth + subs = Submission.count + visit new_submission_path + fill_in('Journal', with: 'Super Mega Journal') + click_on('Create Submission') + assert_equal(Submission.count, subs) + end + + test 'valid form creates new submission' do + mock_auth + subs = Submission.count + visit new_submission_path + fill_in('Journal', with: 'Super Mega Journal') + fill_in('Title', with: 'Alphabetical Order is Good Enough') + check('I am authorized to submit this article.') + click_on('Create Submission') + assert_equal(Submission.count, (subs + 1)) + assert_equal('bob@asdf.com', Submission.last.user.email) + assert_equal(root_path, current_path) + assert_text('Your Submission is now in progress') + end +end diff --git a/test/fixtures/submissions.yml b/test/fixtures/submissions.yml new file mode 100644 index 0000000..d26161f --- /dev/null +++ b/test/fixtures/submissions.yml @@ -0,0 +1,33 @@ +# == Schema Information +# +# Table name: submissions +# +# id :integer not null, primary key +# user_id :integer +# title :string not null +# journal :string +# doi :string +# author :string +# doe :boolean +# grant_number :string +# agreed_to_license :boolean +# created_at :datetime not null +# updated_at :datetime not null +# + +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +sub_one: + title: 'Popcorn is a fruit.' + agreed_to_license: true + user: one + +sub_two: + title: 'Simple Secret Substitution Songs' + user: two + journal: 'Journal of Popcorn Management' + doi: 'doi:10.10.1038/nphys1170' + author: 'Lastname, Firstname' + doe: true + grant_number: 'asdf123' + agreed_to_license: true diff --git a/test/integration/authentication_test.rb b/test/integration/authentication_test.rb index 0b22d60..66f4de6 100644 --- a/test/integration/authentication_test.rb +++ b/test/integration/authentication_test.rb @@ -15,7 +15,7 @@ def teardown def silence_omniauth previous_logger = OmniAuth.config.logger - # OmniAuth.config.logger = Logger.new('/dev/null') + OmniAuth.config.logger = Logger.new('/dev/null') yield ensure OmniAuth.config.logger = previous_logger diff --git a/test/models/submission_test.rb b/test/models/submission_test.rb new file mode 100644 index 0000000..e3f846c --- /dev/null +++ b/test/models/submission_test.rb @@ -0,0 +1,43 @@ +# == Schema Information +# +# Table name: submissions +# +# id :integer not null, primary key +# user_id :integer +# title :string not null +# journal :string +# doi :string +# author :string +# doe :boolean +# grant_number :string +# agreed_to_license :boolean +# created_at :datetime not null +# updated_at :datetime not null +# + +require 'test_helper' + +class SubmissionTest < ActiveSupport::TestCase + test 'valid submission' do + sub = submissions(:sub_one) + assert sub.valid? + end + + test 'invalid without title' do + sub = submissions(:sub_one) + sub.title = '' + assert_not sub.valid? + end + + test 'invalid without user' do + sub = submissions(:sub_one) + sub.user_id = '' + assert_not sub.valid? + end + + test 'invalid without agreed_to_license' do + sub = submissions(:sub_one) + sub.agreed_to_license = false + assert_not sub.valid? + end +end