From 644abef22197c3b3f5fd4d831483a7ed9ec4cdf1 Mon Sep 17 00:00:00 2001 From: Aditya Prakash Date: Mon, 3 Aug 2015 00:44:49 +0530 Subject: [PATCH] Test for keys model and controller Add shoulda-matcher for easier validation checking. Removed project method from keys model cause we are not using it. Stub callback methods of keys model to save hassel. --- Gemfile | 1 + Gemfile.lock | 3 + app/models/key.rb | 5 -- lib/gg/key_fingerprint.rb | 1 - spec/controllers/keys_controller_spec.rb | 42 ++++++++++- spec/factories/keys.rb | 12 ++- spec/models/key_spec.rb | 96 +++++++++++++++++++++++- spec/spec_helper.rb | 1 + 8 files changed, 150 insertions(+), 11 deletions(-) diff --git a/Gemfile b/Gemfile index 366b794a..f68b7f75 100644 --- a/Gemfile +++ b/Gemfile @@ -85,6 +85,7 @@ group :test do gem 'launchy' gem 'rubocop', require: false gem 'haml-lint', require: false + gem 'shoulda-matchers' end # To use ActiveModel has_secure_password diff --git a/Gemfile.lock b/Gemfile.lock index 8388f41f..d32752e2 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -319,6 +319,8 @@ GEM sass-rails (~> 5.0.0.beta1) sprockets (>= 2.3.0) shellany (0.0.1) + shoulda-matchers (2.8.0) + activesupport (>= 3.0.0) sketchily (4.0.1) nokogiri rails (>= 3.1) @@ -417,6 +419,7 @@ DEPENDENCIES rugged (~> 0.21) sass-rails sass-rails-source-maps + shoulda-matchers sketchily sqlite3 test-unit diff --git a/app/models/key.rb b/app/models/key.rb index 88274f9d..194e8bd7 100644 --- a/app/models/key.rb +++ b/app/models/key.rb @@ -18,11 +18,6 @@ class Key < ActiveRecord::Base after_create :add_to_shell after_destroy :remove_from_shell - # projects that has this key - def projects - user.authorized_projects - end - def shell_id "key-#{id}" end diff --git a/lib/gg/key_fingerprint.rb b/lib/gg/key_fingerprint.rb index 4848df46..e671af8b 100644 --- a/lib/gg/key_fingerprint.rb +++ b/lib/gg/key_fingerprint.rb @@ -23,7 +23,6 @@ def fingerprint cmd_output, cmd_status = popen(cmd, '/tmp') end - puts cmd_status, cmd_output return nil unless cmd_status.zero? # 16 hex bytes separated by ':', optionally starting with "MD5:" diff --git a/spec/controllers/keys_controller_spec.rb b/spec/controllers/keys_controller_spec.rb index edefa692..9a38c65e 100644 --- a/spec/controllers/keys_controller_spec.rb +++ b/spec/controllers/keys_controller_spec.rb @@ -1,5 +1,45 @@ require 'spec_helper' -RSpec.describe KeysController, type: :controller do +describe KeysController, type: :controller do + let(:user) { create(:user) } + before { sign_in(user) } + describe 'GET index' do + it 'renders the index template' do + get :index + expect(response).to render_template('index') + end + end + + describe 'POST create' do + before do + allow_any_instance_of(Key).to receive(:add_to_shell).and_return(true) + end + it 'adds key and redirects to key path' do + ssh_key = + 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCx3ke+rnMT/ILY81K1un1CWf9ghcP' + + 'glIlV7pMV2H5AwyC/Dx5x+DyKmNmhBmvCYJ+1we8f0pPXLx2QpyAXw8s0s+sBL/gkiz' + + 'sqqwrUzK9Rlkj58kvNFl8gLQk3qqs8dR6bODP9LQqCGhMFErQtDQTvBq91jhWuIIunu' + + 'mK7T+0GWDMf7O9CNdr/aprYrUfuGLggOdz0oPja792V+ay1xWAHEOueKfGvOGFDbQlc' + + 'TT2uI9wYz9RGkLhDNOo4S74W59xMwMpf77XsoTYxcdrAT7WpTlzaj2usbbGBgcBKx5k' + + 'b0dPBOQ3rQadtZnLjN2dZAeapUO2MElyX0lxt1nrbIKC2 addie@host.localdomain' + post :create, key: { title: 'test', key: ssh_key } + expect(Key.last.title).to eq('test') + expect(response).to redirect_to(keys_path) + end + end + + describe 'DELETE destroy' do + before do + allow_any_instance_of(Key).to receive(:add_to_shell).and_return(true) + allow_any_instance_of(Key).to receive(:remove_from_shell).and_return(true) + @request.env['HTTP_REFERER'] = 'http://test.host/keys' + end + it 'removes key and redirects to key path' do + key = create(:key, user: user) + delete :destroy, id: key.id + expect(Key.all.count).to be(0) + expect(response).to redirect_to(keys_path) + end + end end diff --git a/spec/factories/keys.rb b/spec/factories/keys.rb index 900101e6..1807655a 100644 --- a/spec/factories/keys.rb +++ b/spec/factories/keys.rb @@ -1,7 +1,15 @@ FactoryGirl.define do + factory :key do - key 'MyText' + association :user + sequence :key do |n| + 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCx3ke+rnMT/ILY81K1un1CWf9ghcPgl' + + 'IlV7pMV2H5AwyC/Dx5x+DyKmNmhBmvCYJ+1we8f0pPXLx2QpyAXw8s0s+sBL/gkizsqqw' + + 'rUzK9Rlkj58kvNFl8gLQk3qqs8dR6bODP9LQqCGhMFErQtDQTvBq91jhWuIIunumK7T+0' + + 'GWDMf7O9CNdr/aprYrUfuGLggOdz0oPja792V+ay1xWAHEOueKfGvOGFDbQlcTT2uI9wY' + + 'z9RGkLhDNOo4S74W59xMwMpf77XsoTYxcdrAT7WpTlzaj2usbbGBgcBKx5kb0dPBOQ3rQ' + + "adtZnLjN2dZAeapUO2MElyX0lxt1nrbIKC#{n} addie@localhost.localdomain" + end title 'MyString' - fingerprint 'MyString' end end diff --git a/spec/models/key_spec.rb b/spec/models/key_spec.rb index eb9ec971..3887f843 100644 --- a/spec/models/key_spec.rb +++ b/spec/models/key_spec.rb @@ -1,5 +1,97 @@ require 'spec_helper' -RSpec.describe Key, type: :model do - pending 'add some examples to (or delete) #{__FILE__}' +describe Key do + describe 'Associations' do + it { is_expected.to belong_to(:user) } + end + + describe 'Validation' do + it { is_expected.to validate_presence_of(:title) } + it { is_expected.to validate_presence_of(:key) } + it { is_expected.to validate_length_of(:title) } + it { is_expected.to validate_length_of(:key) } + end + + describe 'Methods' do + before do + allow_any_instance_of(Key).to receive(:add_to_shell).and_return(true) + end + + context 'shell_id' do + let(:key) { create(:key) } + + it 'formats id properly' do + expect(key.shell_id).to eq("key-#{key.id}") + end + end + end + + describe 'validation of' do + before do + allow_any_instance_of(Key).to receive(:add_to_shell).and_return(true) + end + + context 'uniqueness' do + let(:user) { create(:user) } + let(:dummy_key) { create(:key, user: user) } + + it 'accepts the key once' do + expect(build(:key, user: user)).to be_valid + end + + it 'does not accept the exact same key twice' do + expect(build(:key, key: dummy_key.key, user: user)).not_to be_valid + end + + it 'does not accept a duplicate key with a different comment' do + duplicate = build(:key, key: dummy_key.key, user: user) + duplicate.key << ' extra comment' + expect(duplicate).not_to be_valid + end + end + + context 'fingerprintable key' do + it 'accepts the fingerprintable key' do + expect(build(:key)).to be_valid + end + + it 'rejects an unfingerprintable key that contains a space' do + key = build(:key) + + # Not always the middle, but close enough + key.key = key.key[0..100] + ' ' + key.key[101..-1] + + expect(key).not_to be_valid + end + + it 'rejects the unfingerprintable key (not a key)' do + expect(build(:key, key: 'ssh-rsa an-invalid-key==')).not_to be_valid + end + + it 'rejects the multiple line key' do + key = build(:key) + key.key.gsub!(' ', '\n') + expect(key).not_to be_valid + end + end + end + + describe 'callbacks' do + before do + allow(Gg::Shell).to receive(:remove_key).and_return(true) + allow(Gg::Shell).to receive(:add_key).and_return(true) + end + + it 'should add new key to authorized_file' do + key = build(:key, id: 7) + expect(Gg::Shell).to receive(:add_key).with(key.shell_id, key.key) + key.save + end + + it 'should remove key from authorized_file' do + key = create(:key) + expect(Gg::Shell).to receive(:remove_key).with(key.shell_id, key.key) + key.destroy + end + end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 6ae33367..21d4cfef 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -3,6 +3,7 @@ require File.expand_path('../../config/environment', __FILE__) require 'rspec/rails' require 'capybara/rspec' +require 'shoulda/matchers' # Requires supporting ruby files with custom matchers and macros, etc, # in spec/support/ and its subdirectories.