Commit 35643f4b by John Doe

added specs for db_streams controller

parent b19170be
# frozen_string_literal: true
# controller for DbStreams
class DbElementsController < ApplicationController
before_action :authenticate_user!
end
...@@ -3,30 +3,40 @@ ...@@ -3,30 +3,40 @@
# Controller for DbFolders # Controller for DbFolders
class DbFoldersController < ApplicationController class DbFoldersController < ApplicationController
before_action :authenticate_user! before_action :authenticate_user!
before_action :set_folder, only: [:show, :update]
before_action :authorize_viewer, only: [:show]
before_action :authorize_owner, only: [:update]
def show # GET /db_folders.json
folder = DbFolder.find(params[:id]) def show; end
render json: folder, shallow: false
end
#TODO: create info stream on folders on edit # PATCH/PUT /db_folders/1.json
# TODO: create info stream on folders on edit
def update def update
folder = DbFolder.find(params[:id]) adapter = DbAdapter.new(@db.url)
adapter = DbAdapter.new(folder.db.url) @service = EditFolder.new(adapter)
service = EditFolder.new(adapter) @service.run(@db_folder, folder_params)
service.run(folder, folder_params) render status: @service.success? ? :ok : :unprocessable_entity
if service.success?
render json: {data: folder, messages: service}, shallow: false
else
render json: {data: nil, messages: service},
status: :unprocessable_entity
end
end end
private private
def folder_params def folder_params
params.permit(:name, :description,:hidden) params.permit(:name, :description, :hidden)
end end
def set_folder
@db_folder = DbFolder.find(params[:id])
@db = @db_folder.db
@nilm = @db.nilm
end
# authorization based on nilms
def authorize_owner
head :unauthorized unless current_user.owns_nilm?(@nilm)
end
def authorize_viewer
head :unauthorized unless current_user.views_nilm?(@nilm)
end
end end
...@@ -3,28 +3,38 @@ ...@@ -3,28 +3,38 @@
# Controller for DbStreams # Controller for DbStreams
class DbStreamsController < ApplicationController class DbStreamsController < ApplicationController
before_action :authenticate_user! before_action :authenticate_user!
before_action :set_stream, only: [:update]
before_action :authorize_owner, only: [:update]
def update def update
stream = DbStream.find(params[:id]) adapter = DbAdapter.new(@db.url)
adapter = DbAdapter.new(stream.db.url) @service = EditStream.new(adapter)
service = EditStream.new(adapter) @service.run(@db_stream, stream_params)
service.run(stream, stream_params) render status: @service.success? ? :ok : :unprocessable_entity
if service.success?
render json: {data: stream, messages: service}
else
render json: {data: nil, messages: service},
status: :unprocessable_entity
end
end end
private private
def stream_params def stream_params
params.require(:stream) params.permit(:name, :description, :name_abbrev, :hidden,
.permit(:name, :description, :name_abbrev, :hidden,
db_elements_attributes: db_elements_attributes:
[:id, :name, :units, [:id, :name, :units, :default_max,
:default_max, :default_min, :scale_factor, :offset, :default_min, :scale_factor,
:plottable, :discrete]) :offset, :plottable, :discrete])
end
def set_stream
@db_stream = DbStream.find(params[:id])
@db = @db_stream.db
@nilm = @db.nilm
end
# authorization based on nilms
def authorize_owner
head :unauthorized unless current_user.owns_nilm?(@nilm)
end
def authorize_viewer
head :unauthorized unless current_user.views_nilm?(@nilm)
end end
end end
...@@ -10,9 +10,6 @@ class DbsController < ApplicationController ...@@ -10,9 +10,6 @@ class DbsController < ApplicationController
# GET /dbs # GET /dbs
# GET /dbs.json # GET /dbs.json
def show def show
db = Db.find(params[:id])
head(:unauthorized) && return unless current_user.views_nilm?(db.nilm)
render json: db
end end
# PATCH/PUT /dbs/1 # PATCH/PUT /dbs/1
......
# frozen_string_literal: true
json.extract! db_stream, :id, :name, :description, :path, :start_time, json.extract! db_stream, :id, :name, :description, :path, :start_time,
:end_time, :size_on_disk, :total_rows, :total_time, :end_time, :size_on_disk, :total_rows, :total_time,
:data_type, :name_abbrev, :delete_locked, :hidden :data_type, :name_abbrev, :delete_locked, :hidden
json.elements json.array! db_stream.elements, json.elements do
json.array! db_stream.db_elements,
partial: 'db_streams/db_element', partial: 'db_streams/db_element',
as: :db_element as: :db_element
end
json.partial! "db_folders/db_folder", db_folder: @db_folder, shallow: false # frozen_string_literal: true
json.partial! 'db_streams/db_stream',
db_folder: @db_stream
# frozen_string_literal: true
json.data do json.data do
json.partial! "db_folders/db_folder", db_folder: @db_folder, shallow: false json.partial! 'db_streams/db_stream',
db_stream: @db_stream
end end
json.partial! "helpers/messages", service: @service json.partial! 'helpers/messages', service: @service
json.partial! "dbs/db", nilm: @db json.partial! "dbs/db", db: @db
Rails.application.routes.draw do Rails.application.routes.draw do
resources :nilms, only: [:index, :show, :update]
resources :dbs, only: [:show, :update]
resources :db_folders, only: [:show, :update]
resources :db_streams, only: [:update]
mount_devise_token_auth_for 'User', at: 'auth'
resources :user_groups resources :user_groups
resources :permissions resources :permissions
mount_devise_token_auth_for 'User', at: 'auth'
resources :db_decimations
resources :nilms
resources :dbs
resources :db_streams
resources :db_files
resources :db_folders
end end
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe DbElementsController, type: :controller do
end
# frozen_string_literal: true # frozen_string_literal: true
require 'rails_helper' require 'rails_helper'
RSpec.describe DbFoldersController, type: :controller do RSpec.describe DbFoldersController, type: :request do
let(:john) { create(:user, first_name: 'John') }
let(:steve) { create(:user, first_name: 'Steve') }
let(:john_nilm) { create(:nilm, name: "John's NILM", admins: [john]) }
let(:john_folder) do
create(:db_folder, name: 'John Folder',
parent: john_nilm.db.root_folder,
db: john_nilm.db)
end
let(:lab_nilm) { create(:nilm, name: 'Lab NILM', owners: [john]) }
let(:lab_folder) do
create(:db_folder, name: 'Lab Folder',
parent: lab_nilm.db.root_folder,
db: lab_nilm.db)
end
# index action does not exist
describe 'GET show' do
before do
john.confirm
steve.confirm
end
context 'with any permissions' do
it 'returns the db_folder as json' do
# john has some permission on all 3 nilms
@auth_headers = john.create_new_auth_token
[john_folder, lab_folder].each do |folder|
get "/db_folders/#{folder.id}.json",
headers: @auth_headers
expect(response.status).to eq(200)
expect(response.header['Content-Type']).to include('application/json')
body = JSON.parse(response.body)
expect(body['name']).to eq(folder.name)
# contains rendered streams & subfolders (empty, but present)
expect(body['shallow']).to be(false)
end
end
end
context 'without permissions' do
it 'returns unauthorized' do
# steve does NOT have permissions on john_nilm
@auth_headers = steve.create_new_auth_token
get "/db_folders/#{john_folder.id}.json",
headers: @auth_headers
expect(response.status).to eq(401)
end
end
context 'without sign-in' do
it 'returns unauthorized' do
# no headers: nobody is signed in, deny all
get "/db_folders/#{john_folder.id}.json"
expect(response.status).to eq(401)
end
end
end
describe 'PUT update' do
before do
john.confirm
steve.confirm
@mock_adapter = double(DbAdapter) # MockDbAdapter.new #instance_double(DbAdapter)
@db_success = { error: false, msg: 'success' }
@db_failure = { error: true, msg: 'dberror' }
allow(DbAdapter).to receive(:new).and_return(@mock_adapter)
end
context 'with owner permissions' do
it 'updates nilmdb and local database' do
@auth_headers = john.create_new_auth_token
expect(@mock_adapter).to receive(:set_folder_metadata)
.and_return(@db_success)
put "/db_folders/#{john_folder.id}.json",
params: { name: 'new name' },
headers: @auth_headers
expect(response.status).to eq(200)
expect(john_folder.reload.name).to eq('new name')
expect(response).to have_notice_message
end
it 'does not update if nilmdb update fails' do
@auth_headers = john.create_new_auth_token
expect(@mock_adapter).to receive(:set_folder_metadata)
.and_return(@db_failure)
name = john_folder.name
put "/db_folders/#{john_folder.id}.json",
params: { name: 'new name' },
headers: @auth_headers
expect(response.status).to eq(422)
expect(john_folder.reload.name).to eq(name)
expect(response).to have_error_message(/dberror/)
end
it 'returns 422 on invalid parameters' do
# name cannot be blank
expect(@mock_adapter).to_not receive(:set_folder_metadata)
@auth_headers = john.create_new_auth_token
put "/db_folders/#{john_folder.id}.json",
params: { name: '' },
headers: @auth_headers
expect(response.status).to eq(422)
expect(response).to have_error_message(/blank/)
end
it 'only allows configurable parameters to be changed' do
# should ignore start_time and accept description
expect(@mock_adapter).to receive(:set_folder_metadata)
.and_return(@db_success)
@auth_headers = john.create_new_auth_token
start_time = john_folder.start_time
put "/db_folders/#{john_folder.id}.json",
params: { start_time: start_time + 10, description: 'changed' },
headers: @auth_headers
expect(response.status).to eq(200)
expect(john_folder.reload.start_time).to eq(start_time)
expect(john_folder.description).to eq('changed')
end
end
context 'without owner permissions' do
it 'returns unauthorized' do
@auth_headers = steve.create_new_auth_token
name = john_folder.name
put "/db_folders/#{john_folder.id}.json",
params: { name: 'ignored' },
headers: @auth_headers
expect(response).to have_http_status(:unauthorized)
expect(john_folder.reload.name).to eq(name)
end
end
context 'without sign-in' do
it 'returns unauthorized' do
name = john_folder.name
put "/db_folders/#{john_folder.id}.json",
params: { name: 'ignored' }
expect(response).to have_http_status(:unauthorized)
expect(john_folder.name).to eq(name)
end
end
end
end end
# frozen_string_literal: true # frozen_string_literal: true
require 'rails_helper' require 'rails_helper'
RSpec.describe DbStreamsController, type: :controller do RSpec.describe DbStreamsController, type: :request do
let(:john) { create(:user, first_name: 'John') }
let(:steve) { create(:user, first_name: 'Steve') }
let(:john_nilm) { create(:nilm, name: "John's NILM", admins: [john]) }
let(:lab_nilm) { create(:nilm, name: 'Lab NILM', owners: [john]) }
before do
@stream = create(:db_stream, name: 'John Stream',
db_folder: john_nilm.db.root_folder,
db: john_nilm.db)
end
# index action does not exist
# show action does not exist
describe 'PUT update' do
before do
john.confirm
steve.confirm
@mock_adapter = double(DbAdapter) # MockDbAdapter.new #instance_double(DbAdapter)
@db_success = { error: false, msg: 'success' }
@db_failure = { error: true, msg: 'dberror' }
allow(DbAdapter).to receive(:new).and_return(@mock_adapter)
end
context 'with owner permissions' do
it 'updates nilmdb and local database' do
@auth_headers = john.create_new_auth_token
expect(@mock_adapter).to receive(:set_stream_metadata)
.and_return(@db_success)
elem = @stream.db_elements.first
put "/db_streams/#{@stream.id}.json",
params: { name: 'new name',
db_elements_attributes:
[{ id: elem.id, name: 'changed' }] },
headers: @auth_headers
expect(response.status).to eq(200)
expect(@stream.reload.name).to eq('new name')
expect(elem.reload.name).to eq('changed')
expect(response).to have_notice_message
# check to make sure JSON renders the elements
body = JSON.parse(response.body)
expect(body['data']['elements'].count)
.to eq(@stream.db_elements.count)
end
it 'does not update if nilmdb update fails' do
@auth_headers = john.create_new_auth_token
expect(@mock_adapter).to receive(:set_stream_metadata)
.and_return(@db_failure)
name = @stream.name
put "/db_streams/#{@stream.id}.json",
params: { name: 'new name' },
headers: @auth_headers
expect(response.status).to eq(422)
expect(@stream.reload.name).to eq(name)
expect(response).to have_error_message(/dberror/)
end
it 'returns 422 on invalid stream parameters' do
# name cannot be blank
expect(@mock_adapter).to_not receive(:set_stream_metadata)
@auth_headers = john.create_new_auth_token
put "/db_streams/#{@stream.id}.json",
params: { name: '' },
headers: @auth_headers
expect(response.status).to eq(422)
expect(response).to have_error_message(/blank/)
end
it 'returns 422 on invalid element parameters' do
# elements cannot have the same name
expect(@mock_adapter).to_not receive(:set_stream_metadata)
@auth_headers = john.create_new_auth_token
elem1 = @stream.db_elements.first
elemN = @stream.db_elements.last
put "/db_streams/#{@stream.id}.json",
params: { db_elements_attributes:
[{ id: elem1.id, name: elemN.name }] },
headers: @auth_headers
expect(response.status).to eq(422)
expect(response).to have_error_message(/name/)
end
it 'only allows configurable parameters to be changed' do
# should ignore start_time and accept name
expect(@mock_adapter).to receive(:set_stream_metadata)
.and_return(@db_success)
@auth_headers = john.create_new_auth_token
start_time = @stream.start_time
put "/db_streams/#{@stream.id}.json",
params: { start_time: start_time + 10, name: 'changed' },
headers: @auth_headers
expect(response.status).to eq(200)
expect(@stream.reload.start_time).to eq(start_time)
expect(@stream.name).to eq('changed')
end
end
context 'without owner permissions' do
it 'returns unauthorized' do
@auth_headers = steve.create_new_auth_token
name = @stream.name
put "/db_streams/#{@stream.id}.json",
params: { name: 'ignored' },
headers: @auth_headers
expect(response).to have_http_status(:unauthorized)
expect(@stream.reload.name).to eq(name)
end
end
context 'without sign-in' do
it 'returns unauthorized' do
name = @stream.name
put "/db_streams/#{@stream.id}.json",
params: { name: 'ignored' }
expect(response).to have_http_status(:unauthorized)
expect(@stream.name).to eq(name)
end
end
end
end end
...@@ -87,7 +87,7 @@ RSpec.describe DbsController, type: :request do ...@@ -87,7 +87,7 @@ RSpec.describe DbsController, type: :request do
# should ignore size and accept max_points # should ignore size and accept max_points
@auth_headers = john.create_new_auth_token @auth_headers = john.create_new_auth_token
size = john_nilm.db.size_db size = john_nilm.db.size_db
num_points = pete_nilm.db.max_points_per_plot num_points = john_nilm.db.max_points_per_plot
put "/dbs/#{john_nilm.db.id}.json", put "/dbs/#{john_nilm.db.id}.json",
params: {max_points_per_plot: num_points+10, size_db: size+10}, params: {max_points_per_plot: num_points+10, size_db: size+10},
headers: @auth_headers headers: @auth_headers
......
...@@ -3,9 +3,14 @@ ...@@ -3,9 +3,14 @@
# generic DbStream # generic DbStream
FactoryGirl.define do FactoryGirl.define do
factory :db_element do factory :db_element do
db_stream name { Faker::Lorem.unique.words(3) }
name { Faker::Lorem.word } units 'volts'
sequence(:column)
default_max 100
default_min 0
scale_factor 1.0 scale_factor 1.0
offset 0.0 offset 0.0
plottable true
discrete false
end end
end end
...@@ -4,5 +4,11 @@ ...@@ -4,5 +4,11 @@
FactoryGirl.define do FactoryGirl.define do
factory :db_folder, aliases: [:root_folder] do factory :db_folder, aliases: [:root_folder] do
name { Faker::Lorem.word } name { Faker::Lorem.word }
description { Faker::Lorem.sentence }
start_time { Faker::Number.number(6)}
end_time { start_time + Faker::Number.number(5) }
size_on_disk { Faker::Number.number(6) }
hidden false
path { "/root/#{Faker::Lorem.unique.word}" }
end end
end end
...@@ -3,7 +3,25 @@ ...@@ -3,7 +3,25 @@
# generic DbStream # generic DbStream
FactoryGirl.define do FactoryGirl.define do
factory :db_stream do factory :db_stream do
name { Faker::Lorem.word } name { Faker::Lorem.words(3) }
data_type {"float32_1"} name_abbrev { Faker::Lorem.word }
description { Faker::Lorem.sentence }
delete_locked false
start_time { Faker::Number.number(6)}
end_time { start_time + Faker::Number.number(5) }
size_on_disk { Faker::Number.number(6) }
hidden false
path { "/root/streams/#{Faker::Lorem.unique.word}" }
data_type { "float32_#{elements_count}" }
transient do
elements_count 4
end
after(:create) do |stream, evaluator|
create_list(:db_element,
evaluator.elements_count,
db_stream: stream)
end
end end
end end
...@@ -8,6 +8,7 @@ require 'spec_helper' ...@@ -8,6 +8,7 @@ require 'spec_helper'
require 'rspec/rails' require 'rspec/rails'
require 'support/factory_girl' require 'support/factory_girl'
require 'support/api_messages' require 'support/api_messages'
require 'support/mock_service'
# Add additional requires below this line. Rails is not loaded until this point! # Add additional requires below this line. Rails is not loaded until this point!
......
...@@ -5,7 +5,7 @@ require 'rails_helper' ...@@ -5,7 +5,7 @@ require 'rails_helper'
describe 'EditStream service' do describe 'EditStream service' do
let(:db_adapter) { instance_double(DbAdapter) } let(:db_adapter) { instance_double(DbAdapter) }
let(:stream) { FactoryGirl.create(:db_stream, path: '/stream/path', name: 'old') } let(:stream) { FactoryGirl.create(:db_stream, path: '/stream/path', name: 'old') }
let(:element) { FactoryGirl.create(:db_element, db_stream: stream)} let(:element) { stream.db_elements.first}
let(:service) { EditStream.new(db_adapter) } let(:service) { EditStream.new(db_adapter) }
# db adapter return values # db adapter return values
let(:success) { { error: false, msg: '' } } let(:success) { { error: false, msg: '' } }
......
# frozen_string_literal: true
# run method accepts any args
class MockServiceHelper
include ServiceStatus
def run(*_args, **_kwargs)
self
end
end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment