diff --git a/.gitignore b/.gitignore index a2b03a61..43009ea4 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,8 @@ vendor/ log/*.log tmp +coverage + .DS_Store */.DS_Store .DS_Store? diff --git a/.simplecov b/.simplecov new file mode 100644 index 00000000..b81ebfeb --- /dev/null +++ b/.simplecov @@ -0,0 +1,3 @@ +if ENV['COVERAGE'] == 'on' + SimpleCov.start 'rails' +end diff --git a/Gemfile b/Gemfile index b4e3bdf6..8379a7db 100644 --- a/Gemfile +++ b/Gemfile @@ -42,6 +42,8 @@ group :test do gem 'rspec-rails' gem 'factory_girl_rails' gem 'shoulda-matchers' + gem 'simplecov', require: false + gem 'json-schema' end group :production do #this is used on heroku diff --git a/Gemfile.lock b/Gemfile.lock index 5525a8cc..3a5f1b41 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -36,6 +36,7 @@ GEM minitest (~> 5.1) thread_safe (~> 0.3, >= 0.3.4) tzinfo (~> 1.1) + addressable (2.3.8) arel (6.0.3) aws-sdk (1.66.0) aws-sdk-v1 (= 1.66.0) @@ -78,6 +79,7 @@ GEM thread_safe (~> 0.1) warden (~> 1.2.3) diff-lcs (1.2.5) + docile (1.1.5) dotenv (2.0.2) erubis (2.7.0) execjs (2.6.0) @@ -104,6 +106,8 @@ GEM jquery-ui-rails (5.0.5) railties (>= 3.2.16) json (1.8.3) + json-schema (2.6.0) + addressable (~> 2.3.8) kaminari (0.16.3) actionpack (>= 3.0.0) activesupport (>= 3.0.0) @@ -203,6 +207,11 @@ GEM tilt (>= 1.1, < 3) shoulda-matchers (3.0.1) activesupport (>= 4.0.0) + simplecov (0.11.1) + docile (~> 1.1.0) + json (~> 1.8) + simplecov-html (~> 0.10.0) + simplecov-html (0.10.0) slop (3.6.0) sprockets (3.4.0) rack (> 1, < 3) @@ -245,6 +254,7 @@ DEPENDENCIES jquery-rails jquery-ui-rails json + json-schema kaminari paperclip pg @@ -258,9 +268,10 @@ DEPENDENCIES rspec-rails sass-rails shoulda-matchers + simplecov tunemygc uglifier uservoice-ruby BUNDLED WITH - 1.10.6 + 1.11.2 diff --git a/app/controllers/mappings_controller.rb b/app/controllers/mappings_controller.rb index 27567eb4..c20b0153 100644 --- a/app/controllers/mappings_controller.rb +++ b/app/controllers/mappings_controller.rb @@ -15,8 +15,6 @@ class MappingsController < ApplicationController def create @mapping = Mapping.new(mapping_params) - @mapping.map.touch(:updated_at) - if @mapping.save render json: @mapping, status: :created else @@ -28,8 +26,6 @@ class MappingsController < ApplicationController def update @mapping = Mapping.find(params[:id]) - @mapping.map.touch(:updated_at) - if @mapping.update_attributes(mapping_params) head :no_content else @@ -44,8 +40,6 @@ class MappingsController < ApplicationController @mapping.destroy - @map.touch(:updated_at) - head :no_content end diff --git a/app/controllers/maps_controller.rb b/app/controllers/maps_controller.rb index add8a0c1..9ad05810 100644 --- a/app/controllers/maps_controller.rb +++ b/app/controllers/maps_controller.rb @@ -1,5 +1,4 @@ class MapsController < ApplicationController - before_filter :require_user, only: [:create, :update, :screenshot, :destroy] respond_to :html, :json @@ -10,38 +9,24 @@ class MapsController < ApplicationController # GET /explore/featured # GET /explore/mapper/:id def index - - if request.path == "/explore" - redirect_to activemaps_url and return - end + return redirect_to activemaps_url if request.path == "/explore" @current = current_user - @user = nil @maps = [] - @mapperId = nil - - if !params[:page] - page = 1 - else - page = params[:page] - end + page = params[:page].present? ? params[:page] : 1 if request.path.index("/explore/active") != nil @maps = Map.where("maps.permission != ?", "private").order("updated_at DESC").page(page).per(20) @request = "active" - elsif request.path.index("/explore/featured") != nil @maps = Map.where("maps.featured = ? AND maps.permission != ?", true, "private").order("updated_at DESC").page(page).per(20) @request = "featured" - elsif request.path.index('/explore/mine') != nil # looking for maps by me - if !authenticated? - redirect_to activemaps_url and return - end + return redirect_to activemaps_url if !authenticated? + # don't need to exclude private maps because they all belong to you @maps = Map.where("maps.user_id = ?", @current.id).order("updated_at DESC").page(page).per(20) @request = "you" - elsif request.path.index('/explore/mapper/') != nil # looking for maps by a mapper @user = User.find(params[:id]) @maps = Map.where("maps.user_id = ? AND maps.permission != ?", @user.id, "private").order("updated_at DESC").page(page).per(20) @@ -117,7 +102,6 @@ class MapsController < ApplicationController # POST maps def create - @user = current_user @map = Map.new() @map.name = params[:name] @@ -125,40 +109,45 @@ class MapsController < ApplicationController @map.permission = params[:permission] @map.user = @user @map.arranged = false - @map.save if params[:topicsToMap] @all = params[:topicsToMap] @all = @all.split(',') @all.each do |topic| topic = topic.split('/') - @mapping = Mapping.new() - @mapping.user = @user - @mapping.map = @map - @mapping.mappable = Topic.find(topic[0]) - @mapping.xloc = topic[1] - @mapping.yloc = topic[2] - @mapping.save + mapping = Mapping.new() + mapping.user = @user + mapping.mappable = Topic.find(topic[0]) + mapping.xloc = topic[1] + mapping.yloc = topic[2] + @map.topicmappings << mapping + mapping.save end if params[:synapsesToMap] @synAll = params[:synapsesToMap] @synAll = @synAll.split(',') @synAll.each do |synapse_id| - @mapping = Mapping.new() - @mapping.user = @user - @mapping.map = @map - @mapping.mappable = Synapse.find(synapse_id) - @mapping.save + mapping = Mapping.new() + mapping.user = @user + mapping.map = @map + mapping.mappable = Synapse.find(synapse_id) + @map.synapsemappings << mapping + mapping.save end end @map.arranged = true - @map.save end - respond_to do |format| + if @map.save + respond_to do |format| format.json { render :json => @map } + end + else + respond_to do |format| + format.json { render :json => "invalid params" } + end end end diff --git a/app/controllers/metacodes_controller.rb b/app/controllers/metacodes_controller.rb index 5d1e1367..f026c58a 100644 --- a/app/controllers/metacodes_controller.rb +++ b/app/controllers/metacodes_controller.rb @@ -15,24 +15,12 @@ class MetacodesController < ApplicationController redirect_to root_url, notice: "You need to be an admin for that." return false end - render action: "index" + render :index } format.json { render json: @metacodes } end end - ### SHOW IS CURRENTLY DISABLED - # GET /metacodes/1 - # GET /metacodes/1.json -# def show -# @metacode = Metacode.find(params[:id]) -# -# respond_to do |format| -# format.html # show.html.erb -# format.json { render json: @metacode } -# end -# end - # GET /metacodes/new # GET /metacodes/new.json def new @@ -59,7 +47,7 @@ class MetacodesController < ApplicationController format.html { redirect_to metacodes_url, notice: 'Metacode was successfully created.' } format.json { render json: @metacode, status: :created, location: metacodes_url } else - format.html { render action: "new" } + format.html { render :new } format.json { render json: @metacode.errors, status: :unprocessable_entity } end end @@ -71,34 +59,20 @@ class MetacodesController < ApplicationController @metacode = Metacode.find(params[:id]) respond_to do |format| - if @metacode.update_attributes(metacode_params) + if @metacode.update(metacode_params) format.html { redirect_to metacodes_url, notice: 'Metacode was successfully updated.' } format.json { head :no_content } else - format.html { render action: "edit" } + format.html { render :edit } format.json { render json: @metacode.errors, status: :unprocessable_entity } end end end - - ### DESTROY IS CURRENTLY DISABLED - # DELETE /metacodes/1 - # DELETE /metacodes/1.json -# def destroy -# @metacode = Metacode.find(params[:id]) -# @metacode.destroy -# -# respond_to do |format| -# format.html { redirect_to metacodes_url } -# format.json { head :no_content } -# end -# end - private - # Never trust parameters from the scary internet, only allow the white list through. - def metacode_params - params.require(:metacode).permit(:id, :name, :icon, :color) - end + # Never trust parameters from the scary internet, only allow the white list through. + def metacode_params + params.require(:metacode).permit(:id, :name, :icon, :color) + end end diff --git a/app/models/map.rb b/app/models/map.rb index 87019d2a..6c2caca2 100644 --- a/app/models/map.rb +++ b/app/models/map.rb @@ -41,41 +41,41 @@ class Map < ActiveRecord::Base end def topic_count - self.topics.length + topics.length end def synapse_count - self.synapses.length + synapses.length end def user_name - self.user.name + user.name end def user_image - self.user.image.url + user.image.url end def contributor_count - self.contributors.length + contributors.length end def screenshot_url - self.screenshot.url(:thumb) + screenshot.url(:thumb) end def created_at_str - self.created_at.strftime("%m/%d/%Y") + created_at.strftime("%m/%d/%Y") end def updated_at_str - self.updated_at.strftime("%m/%d/%Y") + updated_at.strftime("%m/%d/%Y") end def as_json(options={}) json = super(:methods =>[:user_name, :user_image, :topic_count, :synapse_count, :contributor_count, :screenshot_url], :except => [:screenshot_content_type, :screenshot_file_size, :screenshot_file_name, :screenshot_updated_at]) - json[:created_at_clean] = self.created_at_str - json[:updated_at_clean] = self.updated_at_str + json[:created_at_clean] = created_at_str + json[:updated_at_clean] = updated_at_str json end diff --git a/app/models/mapping.rb b/app/models/mapping.rb index 318aa5cf..425f358d 100644 --- a/app/models/mapping.rb +++ b/app/models/mapping.rb @@ -4,10 +4,13 @@ class Mapping < ActiveRecord::Base scope :synapsemapping, -> { where(mappable_type: :Synapse) } belongs_to :mappable, polymorphic: true - - belongs_to :map, :class_name => "Map", :foreign_key => "map_id" - + belongs_to :map, :class_name => "Map", :foreign_key => "map_id", touch: true belongs_to :user + + validates :xloc, presence: true + validates :yloc, presence: true + validates :map, presence: true + validates :mappable, presence: true def user_name self.user.name diff --git a/app/models/metacode.rb b/app/models/metacode.rb index 03b0f0c0..aa8f9104 100644 --- a/app/models/metacode.rb +++ b/app/models/metacode.rb @@ -1,5 +1,4 @@ class Metacode < ActiveRecord::Base - has_many :in_metacode_sets has_many :metacode_sets, :through => :in_metacode_sets has_many :topics diff --git a/app/models/synapse.rb b/app/models/synapse.rb index 225485e5..ea5889cc 100644 --- a/app/models/synapse.rb +++ b/app/models/synapse.rb @@ -1,5 +1,4 @@ class Synapse < ActiveRecord::Base - belongs_to :user belongs_to :topic1, :class_name => "Topic", :foreign_key => "node1_id" @@ -13,17 +12,25 @@ class Synapse < ActiveRecord::Base validates :permission, presence: true validates :permission, inclusion: { in: Perm::ISSIONS.map(&:to_s) } + validates :category, inclusion: { in: ['from-to', 'both'], allow_nil: true } + + # :nocov: def user_name - self.user.name + user.name end + # :nocov: + # :nocov: def user_image - self.user.image.url + user.image.url end + # :nocov: + # :nocov: def as_json(options={}) super(:methods =>[:user_name, :user_image]) end + # :nocov: ##### PERMISSIONS ###### diff --git a/bin/jenkins-test.sh b/bin/jenkins-test.sh index 313c23b3..f9059d30 100755 --- a/bin/jenkins-test.sh +++ b/bin/jenkins-test.sh @@ -1,7 +1,8 @@ #!/bin/bash -l -#prerequisites -#sudo aptitude -q -y install libpq-dev +# jenkins machine prerequisites +# sudo aptitude -q -y install libpq-dev +# install rvm with user gemsets source "$HOME/.rvm/scripts/rvm" rvm use $(cat .ruby-version) || \ @@ -21,4 +22,4 @@ sed -i -e "s/DB_USERNAME='.*'/DB_USERNAME='jenkins'/" .env #test bundle install rake db:create db:test:prepare -bundle exec rspec +COVERAGE=on bundle exec rspec diff --git a/spec/controllers/mappings_controller_spec.rb b/spec/controllers/mappings_controller_spec.rb index 8a7acda5..ffc9bac9 100644 --- a/spec/controllers/mappings_controller_spec.rb +++ b/spec/controllers/mappings_controller_spec.rb @@ -1,60 +1,16 @@ require 'rails_helper' -# This spec was generated by rspec-rails when you ran the scaffold generator. -# It demonstrates how one might use RSpec to specify the controller code that -# was generated by Rails when you ran the scaffold generator. -# -# It assumes that the implementation code is generated by the rails scaffold -# generator. If you are using any extension libraries to generate different -# controller code, this generated spec may or may not pass. -# -# It only uses APIs available in rails and/or rspec-rails. There are a number -# of tools you can use to make these specs even more expressive, but we're -# sticking to rails and rspec-rails APIs to keep things simple and stable. -# -# Compared to earlier versions of this generator, there is very limited use of -# stubs and message expectations in this spec. Stubs are only used when there -# is no simpler way to get a handle on the object needed for the example. -# Message expectations are only used when there is no simpler way to specify -# that an instance is receiving a specific message. - RSpec.describe MappingsController, type: :controller do - # This should return the minimal set of attributes required to create a valid - # Mapping. As you add validations to Mapping, be sure to - # adjust the attributes here as well. - let(:valid_attributes) do - skip('Add a hash of attributes valid for your model') - end - - let(:invalid_attributes) do - skip('Add a hash of attributes invalid for your model') - end - - # This should return the minimal set of values that should be in the session - # in order to pass any filters (e.g. authentication) defined in - # MappingsController. Be sure to keep this updated too. - let(:valid_session) { {} } - - describe 'GET #index' do - it 'assigns all mappings as @mappings' do - mapping = Mapping.create! valid_attributes - get :index, {}, valid_session - expect(assigns(:mappings)).to eq([mapping]) - end + let!(:mapping) { create(:mapping) } + let(:valid_attributes) { mapping.attributes.except('id') } + let(:invalid_attributes) { { xloc: 0 } } + before :each do + sign_in end describe 'GET #show' do it 'assigns the requested mapping as @mapping' do - mapping = Mapping.create! valid_attributes - get :show, { id: mapping.to_param }, valid_session - expect(assigns(:mapping)).to eq(mapping) - end - end - - describe 'GET #edit' do - it 'assigns the requested mapping as @mapping' do - mapping = Mapping.create! valid_attributes - get :edit, { id: mapping.to_param }, valid_session + get :show, { id: mapping.to_param } expect(assigns(:mapping)).to eq(mapping) end end @@ -63,98 +19,56 @@ RSpec.describe MappingsController, type: :controller do context 'with valid params' do it 'creates a new Mapping' do expect do - post :create, { mapping: valid_attributes }, valid_session + post :create, { mapping: valid_attributes } end.to change(Mapping, :count).by(1) end it 'assigns a newly created mapping as @mapping' do - post :create, { mapping: valid_attributes }, valid_session + post :create, { mapping: valid_attributes } expect(assigns(:mapping)).to be_a(Mapping) expect(assigns(:mapping)).to be_persisted end - - it 'redirects to the created mapping' do - post :create, { mapping: valid_attributes }, valid_session - expect(response).to redirect_to(Mapping.last) - end end context 'with invalid params' do it 'assigns a newly created but unsaved mapping as @mapping' do - post :create, { mapping: invalid_attributes }, valid_session + post :create, { mapping: invalid_attributes } expect(assigns(:mapping)).to be_a_new(Mapping) end - - it "re-renders the 'new' template" do - post :create, { mapping: invalid_attributes }, valid_session - expect(response).to render_template('new') - end end end describe 'PUT #update' do context 'with valid params' do - let(:new_attributes) do - skip('Add a hash of attributes valid for your model') - end + let(:new_attributes) { build(:mapping_random_location).attributes.except('id') } it 'updates the requested mapping' do - mapping = Mapping.create! valid_attributes put :update, - { id: mapping.to_param, mapping: new_attributes }, - valid_session + { id: mapping.to_param, mapping: new_attributes } mapping.reload - skip('Add assertions for updated state') end it 'assigns the requested mapping as @mapping' do - mapping = Mapping.create! valid_attributes put :update, - { id: mapping.to_param, mapping: valid_attributes }, - valid_session + { id: mapping.to_param, mapping: valid_attributes } expect(assigns(:mapping)).to eq(mapping) end - - it 'redirects to the mapping' do - mapping = Mapping.create! valid_attributes - put :update, - { id: mapping.to_param, mapping: valid_attributes }, - valid_session - expect(response).to redirect_to(mapping) - end end context 'with invalid params' do it 'assigns the mapping as @mapping' do - mapping = Mapping.create! valid_attributes put :update, - { id: mapping.to_param, mapping: invalid_attributes }, - valid_session + { id: mapping.to_param, mapping: invalid_attributes } expect(assigns(:mapping)).to eq(mapping) end - - it "re-renders the 'edit' template" do - mapping = Mapping.create! valid_attributes - put :update, - { id: mapping.to_param, mapping: invalid_attributes }, - valid_session - expect(response).to render_template('edit') - end end end describe 'DELETE #destroy' do it 'destroys the requested mapping' do - mapping = Mapping.create! valid_attributes expect do - delete :destroy, { id: mapping.to_param }, valid_session + delete :destroy, { id: mapping.to_param } end.to change(Mapping, :count).by(-1) end - - it 'redirects to the mappings list' do - mapping = Mapping.create! valid_attributes - delete :destroy, { id: mapping.to_param }, valid_session - expect(response).to redirect_to(mappings_url) - end end end diff --git a/spec/controllers/maps_controller_spec.rb b/spec/controllers/maps_controller_spec.rb index fdaa064a..b2f0abec 100644 --- a/spec/controllers/maps_controller_spec.rb +++ b/spec/controllers/maps_controller_spec.rb @@ -1,60 +1,30 @@ require 'rails_helper' -# This spec was generated by rspec-rails when you ran the scaffold generator. -# It demonstrates how one might use RSpec to specify the controller code that -# was generated by Rails when you ran the scaffold generator. -# -# It assumes that the implementation code is generated by the rails scaffold -# generator. If you are using any extension libraries to generate different -# controller code, this generated spec may or may not pass. -# -# It only uses APIs available in rails and/or rspec-rails. There are a number -# of tools you can use to make these specs even more expressive, but we're -# sticking to rails and rspec-rails APIs to keep things simple and stable. -# -# Compared to earlier versions of this generator, there is very limited use of -# stubs and message expectations in this spec. Stubs are only used when there -# is no simpler way to get a handle on the object needed for the example. -# Message expectations are only used when there is no simpler way to specify -# that an instance is receiving a specific message. - RSpec.describe MapsController, type: :controller do - # This should return the minimal set of attributes required to create a valid - # Map. As you add validations to Map, be sure to - # adjust the attributes here as well. - let(:valid_attributes) do - skip('Add a hash of attributes valid for your model') + let(:map) { create(:map) } + let(:valid_attributes) { map.attributes.except(:id) } + let(:invalid_attributes) { { permission: :commons } } + before :each do + sign_in end - let(:invalid_attributes) do - skip('Add a hash of attributes invalid for your model') - end - - # This should return the minimal set of values that should be in the session - # in order to pass any filters (e.g. authentication) defined in - # MapsController. Be sure to keep this updated too. - let(:valid_session) { {} } - describe 'GET #index' do - it 'assigns all maps as @maps' do - map = Map.create! valid_attributes - get :index, {}, valid_session + it 'viewable maps as @maps' do + get :index, {} expect(assigns(:maps)).to eq([map]) end end + describe 'GET #contains' do + it 'returns json matching schema' do + get :contains, { id: map.to_param, format: :json } + expect(response.body).to match_json_schema(:map_contains) + end + end + describe 'GET #show' do it 'assigns the requested map as @map' do - map = Map.create! valid_attributes - get :show, { id: map.to_param }, valid_session - expect(assigns(:map)).to eq(map) - end - end - - describe 'GET #edit' do - it 'assigns the requested map as @map' do - map = Map.create! valid_attributes - get :edit, { id: map.to_param }, valid_session + get :show, { id: map.to_param } expect(assigns(:map)).to eq(map) end end @@ -62,99 +32,72 @@ RSpec.describe MapsController, type: :controller do describe 'POST #create' do context 'with valid params' do it 'creates a new Map' do + map.reload expect do - post :create, { map: valid_attributes }, valid_session + post :create, valid_attributes.merge(format: :json) end.to change(Map, :count).by(1) end it 'assigns a newly created map as @map' do - post :create, { map: valid_attributes }, valid_session + post :create, valid_attributes.merge(format: :json) expect(assigns(:map)).to be_a(Map) expect(assigns(:map)).to be_persisted end - - it 'redirects to the created map' do - post :create, { map: valid_attributes }, valid_session - expect(response).to redirect_to(Map.last) - end end context 'with invalid params' do it 'assigns a newly created but unsaved map as @map' do - post :create, { map: invalid_attributes }, valid_session + post :create, invalid_attributes.merge(format: :json) expect(assigns(:map)).to be_a_new(Map) end - - it "re-renders the 'new' template" do - post :create, { map: invalid_attributes }, valid_session - expect(response).to render_template('new') - end end end describe 'PUT #update' do context 'with valid params' do - let(:new_attributes) do - skip('Add a hash of attributes valid for your model') - end + let(:new_attributes) { { name: "Uncool map", permission: :private } } it 'updates the requested map' do - map = Map.create! valid_attributes put :update, - { id: map.to_param, map: new_attributes }, - valid_session - map.reload - skip('Add assertions for updated state') + { id: map.to_param, map: new_attributes, format: :json } + expect(assigns(:map).name).to eq "Uncool map" + expect(assigns(:map).permission).to eq 'private' end it 'assigns the requested map as @map' do - map = Map.create! valid_attributes put :update, - { id: map.to_param, map: valid_attributes }, - valid_session + { id: map.to_param, map: valid_attributes, format: :json } expect(assigns(:map)).to eq(map) end - - it 'redirects to the map' do - map = Map.create! valid_attributes - put :update, - { id: map.to_param, map: valid_attributes }, - valid_session - expect(response).to redirect_to(map) - end end context 'with invalid params' do it 'assigns the map as @map' do - map = Map.create! valid_attributes put :update, - { id: map.to_param, map: invalid_attributes }, - valid_session + { id: map.to_param, map: invalid_attributes, format: :json } expect(assigns(:map)).to eq(map) end - - it "re-renders the 'edit' template" do - map = Map.create! valid_attributes - put :update, - { id: map.to_param, map: invalid_attributes }, - valid_session - expect(response).to render_template('edit') - end end end describe 'DELETE #destroy' do - it 'destroys the requested map' do - map = Map.create! valid_attributes + let(:unowned_map) { create(:map) } + let(:owned_map) { create(:map, user: controller.current_user) } + + it 'prevents deletion by non-owners' do + unowned_map.reload expect do - delete :destroy, { id: map.to_param }, valid_session - end.to change(Map, :count).by(-1) + delete :destroy, { id: unowned_map.to_param, format: :json } + end.to change(Map, :count).by(0) + expect(response.body).to eq("unauthorized") end - it 'redirects to the maps list' do - map = Map.create! valid_attributes - delete :destroy, { id: map.to_param }, valid_session - expect(response).to redirect_to(maps_url) + it 'deletes owned map' do + owned_map.reload # ensure it's in the database + expect do + delete :destroy, { id: owned_map.to_param, format: :json } + end.to change(Map, :count).by(-1) + expect(response.body).to eq("success") end end end diff --git a/spec/controllers/metacodes_controller_spec.rb b/spec/controllers/metacodes_controller_spec.rb index 6e1ba2b9..d950e77d 100644 --- a/spec/controllers/metacodes_controller_spec.rb +++ b/spec/controllers/metacodes_controller_spec.rb @@ -1,72 +1,30 @@ require 'rails_helper' -# This spec was generated by rspec-rails when you ran the scaffold generator. -# It demonstrates how one might use RSpec to specify the controller code that -# was generated by Rails when you ran the scaffold generator. -# -# It assumes that the implementation code is generated by the rails scaffold -# generator. If you are using any extension libraries to generate different -# controller code, this generated spec may or may not pass. -# -# It only uses APIs available in rails and/or rspec-rails. There are a number -# of tools you can use to make these specs even more expressive, but we're -# sticking to rails and rspec-rails APIs to keep things simple and stable. -# -# Compared to earlier versions of this generator, there is very limited use of -# stubs and message expectations in this spec. Stubs are only used when there -# is no simpler way to get a handle on the object needed for the example. -# Message expectations are only used when there is no simpler way to specify -# that an instance is receiving a specific message. - RSpec.describe MetacodesController, type: :controller do + let(:metacode) { create(:metacode) } + let(:valid_attributes) { metacode.attributes.except('id') } before :each do - @user = create(:user, admin: true) - sign_in @user + sign_in create(:user, admin: true) end - # This should return the minimal set of attributes required to create a valid - # Metacode. As you add validations to Metacode, be sure to - # adjust the attributes here as well. - let(:valid_attributes) do - skip('Add a hash of attributes valid for your model') - end - - let(:invalid_attributes) do - skip('Add a hash of attributes invalid for your model') - end - - # This should return the minimal set of values that should be in the session - # in order to pass any filters (e.g. authentication) defined in - # MetacodesController. Be sure to keep this updated too. - let(:valid_session) { {} } - describe 'GET #index' do it 'assigns all metacodes as @metacodes' do - metacode = Metacode.create! valid_attributes - get :index, {}, valid_session - expect(assigns(:metacodes)).to eq([metacode]) - end - end - - describe 'GET #show' do - it 'assigns the requested metacode as @metacode' do - metacode = Metacode.create! valid_attributes - get :show, { id: metacode.to_param }, valid_session - expect(assigns(:metacode)).to eq(metacode) + metacode.reload # ensure it's created + get :index, {} + expect(Metacode.all.to_a).to eq([metacode]) end end describe 'GET #new' do it 'assigns a new metacode as @metacode' do - get :new, {}, valid_session + get :new, { format: :json } expect(assigns(:metacode)).to be_a_new(Metacode) end end describe 'GET #edit' do it 'assigns the requested metacode as @metacode' do - metacode = Metacode.create! valid_attributes - get :edit, { id: metacode.to_param }, valid_session + get :edit, { id: metacode.to_param } expect(assigns(:metacode)).to eq(metacode) end end @@ -74,32 +32,22 @@ RSpec.describe MetacodesController, type: :controller do describe 'POST #create' do context 'with valid params' do it 'creates a new Metacode' do + metacode.reload # ensure it's present to start expect do - post :create, { metacode: valid_attributes }, valid_session + post :create, { metacode: valid_attributes } end.to change(Metacode, :count).by(1) end - it 'assigns a newly created metacode as @metacode' do - post :create, { metacode: valid_attributes }, valid_session + it 'has the correct attributes' do + post :create, { metacode: valid_attributes } + # expect(Metacode.last.attributes.expect(:id)).to eq(metacode.attributes.except(:id)) expect(assigns(:metacode)).to be_a(Metacode) expect(assigns(:metacode)).to be_persisted end - it 'redirects to the created metacode' do - post :create, { metacode: valid_attributes }, valid_session - expect(response).to redirect_to(Metacode.last) - end - end - - context 'with invalid params' do - it 'assigns a newly created but unsaved metacode as @metacode' do - post :create, { metacode: invalid_attributes }, valid_session - expect(assigns(:metacode)).to be_a_new(Metacode) - end - - it "re-renders the 'new' template" do - post :create, { metacode: invalid_attributes }, valid_session - expect(response).to render_template('new') + it 'redirects to the metacode index' do + post :create, { metacode: valid_attributes } + expect(response).to redirect_to(metacodes_url) end end end @@ -107,66 +55,33 @@ RSpec.describe MetacodesController, type: :controller do describe 'PUT #update' do context 'with valid params' do let(:new_attributes) do - skip('Add a hash of attributes valid for your model') + { icon: 'https://newimages.ca/cool-image.jpg', + color: '#ffffff', + name: 'Cognition' } end it 'updates the requested metacode' do - metacode = Metacode.create! valid_attributes put :update, - { id: metacode.to_param, metacode: new_attributes }, - valid_session + { id: metacode.to_param, metacode: new_attributes } metacode.reload - skip('Add assertions for updated state') - end - - it 'assigns the requested metacode as @metacode' do - metacode = Metacode.create! valid_attributes - put :update, - { id: metacode.to_param, metacode: valid_attributes }, - valid_session - expect(assigns(:metacode)).to eq(metacode) - end - - it 'redirects to the metacode' do - metacode = Metacode.create! valid_attributes - put :update, - { id: metacode.to_param, metacode: valid_attributes }, - valid_session - expect(response).to redirect_to(metacode) - end - end - - context 'with invalid params' do - it 'assigns the metacode as @metacode' do - metacode = Metacode.create! valid_attributes - put :update, - { id: metacode.to_param, metacode: invalid_attributes }, - valid_session - expect(assigns(:metacode)).to eq(metacode) - end - - it "re-renders the 'edit' template" do - metacode = Metacode.create! valid_attributes - put :update, - { id: metacode.to_param, metacode: invalid_attributes }, - valid_session - expect(response).to render_template('edit') + expect(metacode.icon).to eq 'https://newimages.ca/cool-image.jpg' + expect(metacode.color).to eq '#ffffff' + expect(metacode.name).to eq 'Cognition' end end end - describe 'DELETE #destroy' do - it 'destroys the requested metacode' do - metacode = Metacode.create! valid_attributes - expect do - delete :destroy, { id: metacode.to_param }, valid_session - end.to change(Metacode, :count).by(-1) + context 'not admin' do + it 'denies access to create' do + sign_in create(:user, admin: false) + post :create, { metacode: valid_attributes } + expect(response).to redirect_to root_url end - it 'redirects to the metacodes list' do - metacode = Metacode.create! valid_attributes - delete :destroy, { id: metacode.to_param }, valid_session - expect(response).to redirect_to(metacodes_url) + it 'denies access to update' do + sign_in create(:user, admin: false) + post :update, { id: metacode.to_param, metacode: valid_attributes } + expect(response).to redirect_to root_url end end end diff --git a/spec/controllers/synapses_controller_spec.rb b/spec/controllers/synapses_controller_spec.rb index ff05ea6f..478ee6ed 100644 --- a/spec/controllers/synapses_controller_spec.rb +++ b/spec/controllers/synapses_controller_spec.rb @@ -1,60 +1,16 @@ require 'rails_helper' -# This spec was generated by rspec-rails when you ran the scaffold generator. -# It demonstrates how one might use RSpec to specify the controller code that -# was generated by Rails when you ran the scaffold generator. -# -# It assumes that the implementation code is generated by the rails scaffold -# generator. If you are using any extension libraries to generate different -# controller code, this generated spec may or may not pass. -# -# It only uses APIs available in rails and/or rspec-rails. There are a number -# of tools you can use to make these specs even more expressive, but we're -# sticking to rails and rspec-rails APIs to keep things simple and stable. -# -# Compared to earlier versions of this generator, there is very limited use of -# stubs and message expectations in this spec. Stubs are only used when there -# is no simpler way to get a handle on the object needed for the example. -# Message expectations are only used when there is no simpler way to specify -# that an instance is receiving a specific message. - RSpec.describe SynapsesController, type: :controller do - # This should return the minimal set of attributes required to create a valid - # Synapse. As you add validations to Synapse, be sure to - # adjust the attributes here as well. - let(:valid_attributes) do - skip('Add a hash of attributes valid for your model') - end - - let(:invalid_attributes) do - skip('Add a hash of attributes invalid for your model') - end - - # This should return the minimal set of values that should be in the session - # in order to pass any filters (e.g. authentication) defined in - # SynapsesController. Be sure to keep this updated too. - let(:valid_session) { {} } - - describe 'GET #index' do - it 'assigns all synapses as @synapses' do - synapse = Synapse.create! valid_attributes - get :index, {}, valid_session - expect(assigns(:synapses)).to eq([synapse]) - end + let(:synapse) { create(:synapse) } + let(:valid_attributes) { synapse.attributes.except('id') } + let(:invalid_attributes) { { permission: :invalid_lol } } + before :each do + sign_in end describe 'GET #show' do it 'assigns the requested synapse as @synapse' do - synapse = Synapse.create! valid_attributes - get :show, { id: synapse.to_param }, valid_session - expect(assigns(:synapse)).to eq(synapse) - end - end - - describe 'GET #edit' do - it 'assigns the requested synapse as @synapse' do - synapse = Synapse.create! valid_attributes - get :edit, { id: synapse.to_param }, valid_session + get :show, { id: synapse.to_param, format: :json } expect(assigns(:synapse)).to eq(synapse) end end @@ -62,32 +18,28 @@ RSpec.describe SynapsesController, type: :controller do describe 'POST #create' do context 'with valid params' do it 'creates a new Synapse' do + synapse.reload # ensure it's present expect do - post :create, { synapse: valid_attributes }, valid_session + post :create, { synapse: valid_attributes, format: :json } end.to change(Synapse, :count).by(1) end it 'assigns a newly created synapse as @synapse' do - post :create, { synapse: valid_attributes }, valid_session + post :create, { synapse: valid_attributes, format: :json } expect(assigns(:synapse)).to be_a(Synapse) expect(assigns(:synapse)).to be_persisted end - it 'redirects to the created synapse' do - post :create, { synapse: valid_attributes }, valid_session - expect(response).to redirect_to(Synapse.last) + it 'returns 201 CREATED' do + post :create, { synapse: valid_attributes, format: :json } + expect(response.status).to eq 201 end end context 'with invalid params' do - it 'assigns a newly created but unsaved synapse as @synapse' do - post :create, { synapse: invalid_attributes }, valid_session - expect(assigns(:synapse)).to be_a_new(Synapse) - end - - it "re-renders the 'new' template" do - post :create, { synapse: invalid_attributes }, valid_session - expect(response).to render_template('new') + it 'returns 422 UNPROCESSABLE ENTITY' do + post :create, { synapse: invalid_attributes, format: :json } + expect(response.status).to eq 422 end end end @@ -95,66 +47,49 @@ RSpec.describe SynapsesController, type: :controller do describe 'PUT #update' do context 'with valid params' do let(:new_attributes) do - skip('Add a hash of attributes valid for your model') + { desc: 'My new description', + category: 'both', + permission: :public } end it 'updates the requested synapse' do - synapse = Synapse.create! valid_attributes put :update, - { id: synapse.to_param, synapse: new_attributes }, - valid_session + { id: synapse.to_param, synapse: new_attributes, format: :json } synapse.reload - skip('Add assertions for updated state') + expect(synapse.desc).to eq 'My new description' + expect(synapse.category).to eq 'both' + expect(synapse.permission).to eq 'public' end - it 'assigns the requested synapse as @synapse' do - synapse = Synapse.create! valid_attributes + it 'returns 204 NO CONTENT' do put :update, - { id: synapse.to_param, synapse: valid_attributes }, - valid_session - expect(assigns(:synapse)).to eq(synapse) - end - - it 'redirects to the synapse' do - synapse = Synapse.create! valid_attributes - put :update, - { id: synapse.to_param, synapse: valid_attributes }, - valid_session - expect(response).to redirect_to(synapse) + { id: synapse.to_param, synapse: valid_attributes, format: :json } + expect(response.status).to eq 204 end end context 'with invalid params' do it 'assigns the synapse as @synapse' do - synapse = Synapse.create! valid_attributes put :update, - { id: synapse.to_param, synapse: invalid_attributes }, - valid_session + { id: synapse.to_param, synapse: invalid_attributes, format: :json } expect(assigns(:synapse)).to eq(synapse) end - - it "re-renders the 'edit' template" do - synapse = Synapse.create! valid_attributes - put :update, - { id: synapse.to_param, synapse: invalid_attributes }, - valid_session - expect(response).to render_template('edit') - end end end describe 'DELETE #destroy' do + let(:synapse) { create(:synapse, user: controller.current_user) } + it 'destroys the requested synapse' do - synapse = Synapse.create! valid_attributes + synapse.reload # ensure it's present expect do - delete :destroy, { id: synapse.to_param }, valid_session + delete :destroy, { id: synapse.to_param, format: :json } end.to change(Synapse, :count).by(-1) end - it 'redirects to the synapses list' do - synapse = Synapse.create! valid_attributes - delete :destroy, { id: synapse.to_param }, valid_session - expect(response).to redirect_to(synapses_url) + it 'returns 204 NO CONTENT' do + delete :destroy, { id: synapse.to_param, format: :json } + expect(response.status).to eq 204 end end end diff --git a/spec/controllers/topics_controller_spec.rb b/spec/controllers/topics_controller_spec.rb index 35b2156e..2dd999a1 100644 --- a/spec/controllers/topics_controller_spec.rb +++ b/spec/controllers/topics_controller_spec.rb @@ -1,36 +1,16 @@ require 'rails_helper' RSpec.describe TopicsController, type: :controller do - let(:valid_attributes) do - skip('Add a hash of attributes valid for your model') - end - - let(:invalid_attributes) do - skip('Add a hash of attributes invalid for your model') - end - - let(:valid_session) { {} } - - describe 'GET #index' do - it 'assigns all topics as @topics' do - topic = Topic.create! valid_attributes - get :index, {}, valid_session - expect(assigns(:topics)).to eq([topic]) - end + let(:topic) { create(:topic) } + let(:valid_attributes) { topic.attributes.except('id') } + let(:invalid_attributes) { { permission: :invalid_lol } } + before :each do + sign_in end describe 'GET #show' do it 'assigns the requested topic as @topic' do - topic = Topic.create! valid_attributes - get :show, { id: topic.to_param }, valid_session - expect(assigns(:topic)).to eq(topic) - end - end - - describe 'GET #edit' do - it 'assigns the requested topic as @topic' do - topic = Topic.create! valid_attributes - get :edit, { id: topic.to_param }, valid_session + get :show, { id: topic.to_param, format: :json } expect(assigns(:topic)).to eq(topic) end end @@ -38,99 +18,85 @@ RSpec.describe TopicsController, type: :controller do describe 'POST #create' do context 'with valid params' do it 'creates a new Topic' do + topic.reload # ensure it's created expect do - post :create, { topic: valid_attributes }, valid_session + post :create, { topic: valid_attributes, format: :json } end.to change(Topic, :count).by(1) end it 'assigns a newly created topic as @topic' do - post :create, { topic: valid_attributes }, valid_session + post :create, { topic: valid_attributes, format: :json } expect(assigns(:topic)).to be_a(Topic) expect(assigns(:topic)).to be_persisted end - it 'redirects to the created topic' do - post :create, { topic: valid_attributes }, valid_session - expect(response).to redirect_to(Topic.last) + it 'returns 201 CREATED' do + post :create, { topic: valid_attributes, format: :json } + expect(response.status).to eq 201 end end context 'with invalid params' do it 'assigns a newly created but unsaved topic as @topic' do - post :create, { topic: invalid_attributes }, valid_session + post :create, { topic: invalid_attributes, format: :json } expect(assigns(:topic)).to be_a_new(Topic) end - - it "re-renders the 'new' template" do - post :create, { topic: invalid_attributes }, valid_session - expect(response).to render_template('new') - end end end describe 'PUT #update' do context 'with valid params' do let(:new_attributes) do - skip('Add a hash of attributes valid for your model') + { name: 'Cool Topic with no number', + desc: 'This is a cool topic.', + link: 'https://cool-topics.com/4', + permission: :public } end it 'updates the requested topic' do - topic = Topic.create! valid_attributes put :update, - { id: topic.to_param, topic: new_attributes }, - valid_session + { id: topic.to_param, topic: new_attributes, format: :json } topic.reload - skip('Add assertions for updated state') + expect(topic.name).to eq 'Cool Topic with no number' + expect(topic.desc).to eq 'This is a cool topic.' + expect(topic.link).to eq 'https://cool-topics.com/4' + expect(topic.permission).to eq 'public' end it 'assigns the requested topic as @topic' do - topic = Topic.create! valid_attributes put :update, - { id: topic.to_param, topic: valid_attributes }, - valid_session + { id: topic.to_param, topic: valid_attributes, format: :json } expect(assigns(:topic)).to eq(topic) end - it 'redirects to the topic' do - topic = Topic.create! valid_attributes + it 'returns status of no content' do put :update, - { id: topic.to_param, topic: valid_attributes }, - valid_session - expect(response).to redirect_to(topic) + { id: topic.to_param, topic: valid_attributes, format: :json } + expect(response.status).to eq 204 end end context 'with invalid params' do it 'assigns the topic as @topic' do - topic = Topic.create! valid_attributes put :update, - { id: topic.to_param, topic: invalid_attributes }, - valid_session + { id: topic.to_param, topic: invalid_attributes, format: :json } expect(assigns(:topic)).to eq(topic) end - - it "re-renders the 'edit' template" do - topic = Topic.create! valid_attributes - put :update, - { id: topic.to_param, topic: invalid_attributes }, - valid_session - expect(response).to render_template('edit') - end end end describe 'DELETE #destroy' do + let(:owned_topic) { create(:topic, user: controller.current_user) } it 'destroys the requested topic' do - topic = Topic.create! valid_attributes + owned_topic.reload # ensure it's there expect do - delete :destroy, { id: topic.to_param }, valid_session + delete :destroy, { id: owned_topic.to_param, format: :json } end.to change(Topic, :count).by(-1) end - it 'redirects to the topics list' do - topic = Topic.create! valid_attributes - delete :destroy, { id: topic.to_param }, valid_session - expect(response).to redirect_to(topics_url) + it 'return 204 NO CONTENT' do + delete :destroy, { id: topic.to_param, format: :json } + expect(response.status).to eq 204 end end end diff --git a/spec/factories/mappings.rb b/spec/factories/mappings.rb new file mode 100644 index 00000000..bed0b754 --- /dev/null +++ b/spec/factories/mappings.rb @@ -0,0 +1,14 @@ +FactoryGirl.define do + factory :mapping do + xloc 0 + yloc 0 + map + user + association :mappable, factory: :topic + + factory :mapping_random_location do + xloc { rand(-100...100) } + yloc { rand(-100...100) } + end + end +end diff --git a/spec/factories/metacodes.rb b/spec/factories/metacodes.rb index 5cfb38f6..eb040e09 100644 --- a/spec/factories/metacodes.rb +++ b/spec/factories/metacodes.rb @@ -1,4 +1,7 @@ FactoryGirl.define do factory :metacode do + sequence(:name) { |n| "Cool Metacode ##{n}" } + icon 'https://images.com/image.png' + color '#cccccc' end end diff --git a/spec/factories/synapses.rb b/spec/factories/synapses.rb index b83a0073..4454a7a4 100644 --- a/spec/factories/synapses.rb +++ b/spec/factories/synapses.rb @@ -1,9 +1,10 @@ FactoryGirl.define do factory :synapse do sequence(:desc) { |n| "Cool synapse ##{n}" } - category :to + category :'from-to' permission :commons association :topic1, factory: :topic association :topic2, factory: :topic + user end end diff --git a/spec/models/mapping_spec.rb b/spec/models/mapping_spec.rb index 32d34796..54c72b88 100644 --- a/spec/models/mapping_spec.rb +++ b/spec/models/mapping_spec.rb @@ -1,5 +1,11 @@ require 'rails_helper' RSpec.describe Mapping, type: :model do - pending "add some examples to (or delete) #{__FILE__}" + it { is_expected.to belong_to :user } + it { is_expected.to belong_to :map } + it { is_expected.to belong_to :mappable } + it { is_expected.to validate_presence_of :xloc } + it { is_expected.to validate_presence_of :yloc } + it { is_expected.to validate_presence_of :map } + it { is_expected.to validate_presence_of :mappable } end diff --git a/spec/models/metacode_spec.rb b/spec/models/metacode_spec.rb index 10571a81..6e6435b0 100644 --- a/spec/models/metacode_spec.rb +++ b/spec/models/metacode_spec.rb @@ -1,6 +1,6 @@ require 'rails_helper' RSpec.describe Metacode, type: :model do - pending "add some examples to (or delete) #{__FILE__}" - it { is_expected.to have_many(:topics) } + it { is_expected.to have_many :topics } + it { is_expected.to have_many :metacode_sets } end diff --git a/spec/models/synapse_spec.rb b/spec/models/synapse_spec.rb index a1069805..dcf85358 100644 --- a/spec/models/synapse_spec.rb +++ b/spec/models/synapse_spec.rb @@ -8,6 +8,7 @@ RSpec.describe Synapse, type: :model do it { is_expected.to have_many :mappings } it { is_expected.to validate_presence_of :permission } it { is_expected.to validate_inclusion_of(:permission).in_array Perm::ISSIONS.map(&:to_s) } + it { is_expected.to validate_inclusion_of(:category).in_array ['from-to', 'both'] } it { is_expected.to validate_length_of(:desc).is_at_least(0) } # TODO don't allow nil context 'permissions' do diff --git a/spec/schemas/map.json b/spec/schemas/map.json new file mode 100644 index 00000000..e69de29b diff --git a/spec/schemas/map_contains.json b/spec/schemas/map_contains.json new file mode 100644 index 00000000..0b4faebf --- /dev/null +++ b/spec/schemas/map_contains.json @@ -0,0 +1,42 @@ +{ + "name": "Map Contents", + "type": "object", + "properties": { + "map": { + "type": "object" + }, + "topics": { + "type": "array", + "items": { + "type": "object" + } + }, + "synapses": { + "type": "array", + "items": { + "type": "object" + } + }, + "mappings": { + "type": "array", + "items": { + "type": "object" + } + }, + "mappers": { + "type": "array", + "items": { + "type": "object" + } + } + }, + "required": [ + "map", + "topics", + "synapses", + "mappings", + "mappers" + ] +} + + diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index a2b164b2..08ffd17f 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,3 +1,6 @@ +require 'simplecov' +require 'support/controller_helpers' + RSpec.configure do |config| config.expect_with :rspec do |expectations| expectations.include_chain_clauses_in_custom_matcher_descriptions = true diff --git a/spec/support/controller_helpers.rb b/spec/support/controller_helpers.rb index 5fe34854..ed0d137a 100644 --- a/spec/support/controller_helpers.rb +++ b/spec/support/controller_helpers.rb @@ -1,4 +1,7 @@ # https://github.com/plataformatec/devise/wiki/How-To:-Stub-authentication-in-controller-specs + +require 'devise' + module ControllerHelpers # rubocop:disable Metrics/AbcSize def sign_in(user = create(:user)) @@ -7,6 +10,7 @@ module ControllerHelpers receive(:authenticate!).and_throw(:warden, scope: :user) ) else # simulate authenticated + allow_message_expectations_on_nil allow(request.env['warden']).to( receive(:authenticate!).and_return(user) ) @@ -15,3 +19,8 @@ module ControllerHelpers end # rubocop:enable Metrics/AbcSize end + +RSpec.configure do |config| + config.include Devise::TestHelpers, :type => :controller + config.include ControllerHelpers, :type => :controller +end diff --git a/spec/support/schema_matcher.rb b/spec/support/schema_matcher.rb new file mode 100644 index 00000000..b2a89352 --- /dev/null +++ b/spec/support/schema_matcher.rb @@ -0,0 +1,7 @@ +RSpec::Matchers.define :match_json_schema do |schema| + match do |json| + schema_directory = Rails.root.join('spec', 'schemas').to_s + schema_path = "#{schema_directory}/#{schema}.json" + JSON::Validator.validate!(schema_path, json) + end +end