Merge pull request #1447 from kreuzwerker/feature/agent-edit-simplification

Improve agent and scenario forms

Dominik Sander 8 years ago
parent
commit
9202c84406

+ 11 - 8
.travis.yml

@@ -7,6 +7,8 @@ services:
7 7
 env:
8 8
   global:
9 9
     - APP_SECRET_TOKEN=b2724973fd81c2f4ac0f92ac48eb3f0152c4a11824c122bcf783419a4c51d8b9bba81c8ba6a66c7de599677c7f486242cf819775c433908e77c739c5c8ae118d
10
+    - RSPEC_TASK=spec:nofeatures
11
+    - COVERALLS_PARALLEL=true
10 12
     - secure: fzmSI7PQz6CJiIJNAtLAuy3TMmYCrK4bUil3uufh8JkHfpSGWOZt2i6fZ8yZ7pzwG5Aw7eZDgdFsNcEPJlgUDJhlwjg+QxCJslhotTQ9qI3Ieo85peWlU9dZFTOZcrCu0net/hY2FE4ZpTRb5r8A/DRv9ukA8P8tShhePCjckgg=
11 13
     - secure: YjW07LpRSiC9xB6PhLQ4LVv2VphvF3IacV43PLfvzdagjy14yAwKXTUlSadgRaMbndB2dlCTe3YcY11a/xtX/2HDrF14NHPXQdL7e2dJUS3CDLSKZK26x1SOiaaDIrl1jO1xr5kOUd+564MAcNUzDTJQR4CrWl/5t6EwW4iYQVc=
12 14
     - secure: RJiSTB9Anax6uL6mgYY1m42w71ohlsfIlVCk7ho6W19ZfSzQOfom0mBdeNwfgmXsMMnvnqatfxSg8k3C//pRtI/tjzAovHd7t1YIN1IkDNf9uSpzrIeXXc4fSHaVxnl512oI/eBQy9MSBjVZjrg5XEzLKKEGsZCai+ZKB4PS+nM=
@@ -15,17 +17,22 @@ env:
15 17
     - DATABASE_ADAPTER=postgresql DATABASE_USERNAME=postgres
16 18
     - DOCKER_IMAGE=cantino/huginn-single-process DOCKERFILE=docker/single-process/Dockerfile
17 19
     - DOCKER_IMAGE=cantino/huginn DOCKERFILE=docker/multi-process/Dockerfile
20
+    - RSPEC_TASK=spec:features
18 21
 matrix:
19 22
   exclude:
20 23
     - env: DOCKER_IMAGE=cantino/huginn-single-process DOCKERFILE=docker/single-process/Dockerfile
21 24
     - env: DOCKER_IMAGE=cantino/huginn DOCKERFILE=docker/multi-process/Dockerfile
25
+    - env: RSPEC_TASK=spec:features
22 26
   include:
23 27
     - rvm: 2.3.0
24 28
       env: DATABASE_ADAPTER=mysql2 DOCKER_IMAGE=cantino/huginn-single-process DOCKERFILE=docker/single-process/Dockerfile
25 29
     - rvm: 2.3.0
26 30
       env: DATABASE_ADAPTER=mysql2 DOCKER_IMAGE=cantino/huginn DOCKERFILE=docker/multi-process/Dockerfile
31
+    - rvm: 2.3.0
32
+      env: RSPEC_TASK=spec:features DATABASE_ADAPTER=mysql2
33
+    - rvm: 2.3.0
34
+      env: RSPEC_TASK=spec:features DATABASE_ADAPTER=postgresql DATABASE_USERNAME=postgres
27 35
 rvm:
28
-- 2.0.0
29 36
 - 2.1
30 37
 - 2.2
31 38
 - 2.3.0
@@ -35,7 +42,8 @@ before_install:
35 42
   - sudo apt-get -qq update
36 43
   - sudo apt-get install -y mysql-server
37 44
 script:
38
-  - if [ -z "${DOCKER_IMAGE}" ]; then bundle exec rake db:create db:migrate && bundle exec rake; else ./build_docker_image.sh; fi
45
+  - if [ -z "${DOCKER_IMAGE}" ]; then bundle exec rake db:create db:migrate; else true; fi
46
+  - if [ -z "${DOCKER_IMAGE}" ]; then bundle exec rake $RSPEC_TASK; else ./build_docker_image.sh; fi
39 47
 notifications:
40 48
   irc:
41 49
     channels:
@@ -44,9 +52,4 @@ notifications:
44 52
     - "<%{author}> %{branch} - %{commit} (%{commit_message}): %{message}"
45 53
     - 'Change view : %{compare_url}'
46 54
     - 'Build details : %{build_url}'
47
-  webhooks:
48
-    urls:
49
-      - https://webhooks.gitter.im/e/5f92cc0393c6f1defe0d
50
-    on_success: change  # options: [always|never|change] default: always
51
-    on_failure: always  # options: [always|never|change] default: always
52
-    on_start: never     # options: [always|never|change] default: never
55
+  webhooks: https://coveralls.io/webhook?repo_token=COVERALLS_REPO_TOKEN

+ 2 - 1
Gemfile

@@ -141,7 +141,7 @@ group :development do
141 141
   end
142 142
 
143 143
   group :test do
144
-    gem 'coveralls', require: false
144
+    gem 'coveralls', '~> 0.7.4', require: false
145 145
     gem 'capybara-select2', require: false
146 146
     gem 'delorean'
147 147
     gem 'poltergeist'
@@ -155,6 +155,7 @@ group :development do
155 155
     gem 'shoulda-matchers'
156 156
     gem 'vcr'
157 157
     gem 'webmock', '~> 1.17.4', require: false
158
+    gem 'database_cleaner', '~> 1.5.3'
158 159
   end
159 160
 end
160 161
 

+ 11 - 9
Gemfile.lock

@@ -157,15 +157,16 @@ GEM
157 157
     colorize (0.7.7)
158 158
     concurrent-ruby (1.0.1)
159 159
     cookiejar (0.3.2)
160
-    coveralls (0.7.1)
161
-      multi_json (~> 1.3)
162
-      rest-client
163
-      simplecov (>= 0.7)
164
-      term-ansicolor
165
-      thor
160
+    coveralls (0.7.12)
161
+      multi_json (~> 1.10)
162
+      rest-client (>= 1.6.8, < 2)
163
+      simplecov (~> 0.9.1)
164
+      term-ansicolor (~> 1.3)
165
+      thor (~> 0.19.1)
166 166
     crack (0.4.2)
167 167
       safe_yaml (~> 1.0.0)
168 168
     daemons (1.1.9)
169
+    database_cleaner (1.5.3)
169 170
     debug_inspector (0.0.2)
170 171
     delayed_job (4.1.1)
171 172
       activesupport (>= 3.0, < 5.0)
@@ -522,7 +523,7 @@ GEM
522 523
       net-ssh (>= 2.8.0)
523 524
     string-scrub (0.0.5)
524 525
     systemu (2.6.4)
525
-    term-ansicolor (1.3.0)
526
+    term-ansicolor (1.3.2)
526 527
       tins (~> 1.0)
527 528
     therubyracer (0.12.2)
528 529
       libv8 (~> 3.16.14.0)
@@ -530,7 +531,7 @@ GEM
530 531
     thor (0.19.1)
531 532
     thread_safe (0.3.5)
532 533
     tilt (1.4.1)
533
-    tins (1.3.2)
534
+    tins (1.10.1)
534 535
     treetop (1.5.3)
535 536
       polyglot (~> 0.3)
536 537
     twilio-ruby (3.11.6)
@@ -597,8 +598,9 @@ DEPENDENCIES
597 598
   capistrano-rails (~> 1.1)
598 599
   capybara-select2
599 600
   coffee-rails (~> 4.1.1)
600
-  coveralls
601
+  coveralls (~> 0.7.4)
601 602
   daemons (~> 1.1.9)
603
+  database_cleaner (~> 1.5.3)
602 604
   delayed_job (~> 4.1.0)
603 605
   delayed_job_active_record!
604 606
   delorean

+ 6 - 0
app/assets/javascripts/components/core.js.coffee

@@ -16,6 +16,12 @@ $ ->
16 16
   # Select2 Selects
17 17
   $(".select2").select2(width: 'resolve')
18 18
 
19
+  $(".select2-linked-tags").select2(
20
+    width: 'resolve',
21
+    formatSelection: (obj) ->
22
+      "<a href=\"#{this.element.data('urlPrefix')}/#{obj.id}/edit\" onClick=\"Utils.select2TagClickHandler(event, this)\">#{Utils.escape(obj.text)}</a>"
23
+  )
24
+
19 25
   # Helper for selecting text when clicked
20 26
   $('.selectable-text').each ->
21 27
     $(this).click ->

+ 29 - 0
app/assets/javascripts/components/utils.js.coffee

@@ -132,3 +132,32 @@ class @Utils
132 132
       .fail (xhr, status, error) ->
133 133
         alert('Error: ' + error)
134 134
         callback()
135
+
136
+  @select2TagClickHandler: (e, elem) ->
137
+    if e.which == 1
138
+      window.location = $(elem).attr('href')
139
+    else
140
+      window.open($(elem).attr('href'))
141
+
142
+  # _.escape from underscore: https://github.com/jashkenas/underscore/blob/1e68f06610fa4ecb7f2c45d1eb2ad0173d6a2cc1/underscore.js#L1411-L1436
143
+  escapeMap =
144
+    '&': '&amp;'
145
+    '<': '&lt;'
146
+    '>': '&gt;'
147
+    '"': '&quot;'
148
+    '\'': '&#x27;'
149
+    '`': '&#x60;'
150
+
151
+  createEscaper = (map) ->
152
+    escaper = (match) ->
153
+      map[match]
154
+
155
+    # Regexes for identifying a key that needs to be escaped.
156
+    source = '(?:' + Object.keys(map).join('|') + ')'
157
+    testRegexp = RegExp(source)
158
+    replaceRegexp = RegExp(source, 'g')
159
+    (string) ->
160
+      string = if string == null then '' else '' + string
161
+      if testRegexp.test(string) then string.replace(replaceRegexp, escaper) else string
162
+
163
+  @escape = createEscaper(escapeMap)

+ 19 - 2
app/assets/javascripts/pages/agent-edit-page.js.coffee

@@ -13,6 +13,15 @@ class @AgentEditPage
13 13
           e.preventDefault()
14 14
           alert 'Sorry, there appears to be an error in your JSON input. Please fix it before continuing.'
15 15
 
16
+      if $(".link-region").length && $(".link-region").data("can-receive-events") == false
17
+        $(".link-region .select2-linked-tags option:selected").removeAttr('selected')
18
+
19
+      if $(".control-link-region").length && $(".control-link-region").data("can-control-other-agents") == false
20
+        $(".control-link-region .select2-linked-tags option:selected").removeAttr('selected')
21
+
22
+      if $(".event-related-region").length && $(".event-related-region").data("can-create-events") == false
23
+        $(".event-related-region .select2-linked-tags option:selected").removeAttr('selected')
24
+
16 25
     $("#agent_name").each ->
17 26
       # Select the number suffix if this is a cloned agent.
18 27
       if matches = this.value.match(/ \(\d+\)$/)
@@ -103,24 +112,32 @@ class @AgentEditPage
103 112
     $(".link-region .select2-container").hide()
104 113
     $(".link-region .propagate-immediately").hide()
105 114
     $(".link-region .cannot-receive-events").show()
115
+    $(".link-region").data("can-receive-events", false)
106 116
 
107 117
   showLinks: ->
108 118
     $(".link-region .select2-container").show()
109 119
     $(".link-region .propagate-immediately").show()
110 120
     $(".link-region .cannot-receive-events").hide()
121
+    $(".link-region").data("can-receive-events", true)
111 122
     @showEventDescriptions()
112 123
 
113 124
   hideControlLinks: ->
114 125
     $(".control-link-region").hide()
126
+    $(".control-link-region").data("can-control-other-agents", false)
115 127
 
116 128
   showControlLinks: ->
117 129
     $(".control-link-region").show()
130
+    $(".control-link-region").data("can-control-other-agents", true)
118 131
 
119 132
   hideEventCreation: ->
120
-    $(".event-related-region").hide()
133
+    $(".event-related-region .select2-container").hide()
134
+    $(".event-related-region .cannot-create-events").show()
135
+    $(".event-related-region").data("can-create-events", false)
121 136
 
122 137
   showEventCreation: ->
123
-    $(".event-related-region").show()
138
+    $(".event-related-region .select2-container").show()
139
+    $(".event-related-region .cannot-create-events").hide()
140
+    $(".event-related-region").data("can-create-events", true)
124 141
 
125 142
   showEventDescriptions: ->
126 143
     if $("#agent_source_ids").val()

+ 6 - 21
app/models/agent.rb

@@ -24,16 +24,17 @@ class Agent < ActiveRecord::Base
24 24
 
25 25
   EVENT_RETENTION_SCHEDULES = [["Forever", 0], ['1 hour', 1.hour], ['6 hours', 6.hours], ["1 day", 1.day], *([2, 3, 4, 5, 7, 14, 21, 30, 45, 90, 180, 365].map {|n| ["#{n} days", n.days] })]
26 26
 
27
-  attr_accessible :options, :memory, :name, :type, :schedule, :controller_ids, :control_target_ids, :disabled, :source_ids, :scenario_ids, :keep_events_for, :propagate_immediately, :drop_pending_events
27
+  attr_accessible :options, :memory, :name, :type, :schedule, :controller_ids, :control_target_ids, :disabled, :source_ids, :receiver_ids, :scenario_ids, :keep_events_for, :propagate_immediately, :drop_pending_events
28 28
 
29 29
   json_serialize :options, :memory
30 30
 
31 31
   validates_presence_of :name, :user
32 32
   validates_inclusion_of :keep_events_for, :in => EVENT_RETENTION_SCHEDULES.map(&:last)
33
-  validate :sources_are_owned
34
-  validate :controllers_are_owned
35
-  validate :control_targets_are_owned
36
-  validate :scenarios_are_owned
33
+  validates :sources, owned_by: :user_id
34
+  validates :receivers, owned_by: :user_id
35
+  validates :controllers, owned_by: :user_id
36
+  validates :control_targets, owned_by: :user_id
37
+  validates :scenarios, owned_by: :user_id
37 38
   validate :validate_schedule
38 39
   validate :validate_options
39 40
 
@@ -267,22 +268,6 @@ class Agent < ActiveRecord::Base
267 268
   
268 269
   private
269 270
   
270
-  def sources_are_owned
271
-    errors.add(:sources, "must be owned by you") unless sources.all? {|s| s.user_id == user_id }
272
-  end
273
-  
274
-  def controllers_are_owned
275
-    errors.add(:controllers, "must be owned by you") unless controllers.all? {|s| s.user_id == user_id }
276
-  end
277
-
278
-  def control_targets_are_owned
279
-    errors.add(:control_targets, "must be owned by you") unless control_targets.all? {|s| s.user_id == user_id }
280
-  end
281
-
282
-  def scenarios_are_owned
283
-    errors.add(:scenarios, "must be owned by you") unless scenarios.all? {|s| s.user_id == user_id }
284
-  end
285
-
286 271
   def validate_schedule
287 272
     unless cannot_be_scheduled?
288 273
       errors.add(:schedule, "is not a valid schedule") unless SCHEDULES.include?(schedule.to_s)

+ 6 - 0
app/validators/owned_by_validator.rb

@@ -0,0 +1,6 @@
1
+class OwnedByValidator < ActiveModel::EachValidator
2
+  def validate_each(record, attribute, association)
3
+    return if association.all? {|s| s[options[:with]] == record[options[:with]] }
4
+    record.errors[attribute] << "must be owned by you"
5
+  end
6
+end

+ 17 - 3
app/views/agents/_form.html.erb

@@ -68,7 +68,7 @@
68 68
                   <%= f.select(:control_target_ids,
69 69
                                options_for_select(current_user.agents.map {|s| [s.name, s.id] },
70 70
                                                   @agent.control_target_ids),
71
-                               {}, { multiple: true, size: 5, class: 'select2 form-control' }) %>
71
+                               {}, { multiple: true, size: 5, class: 'select2-linked-tags form-control', data: {url_prefix: '/agents'}}) %>
72 72
                 </div>
73 73
               </div>
74 74
             </div>
@@ -83,12 +83,13 @@
83 83
 
84 84
             <div class="form-group">
85 85
               <%= f.label :sources %>
86
+              <span class="glyphicon glyphicon-question-sign hover-help" data-content="This Agent will receive events from the selected Agents."></span>
86 87
               <div class="link-region" data-can-receive-events="<%= @agent.can_receive_events? %>">
87 88
                 <% eventSources = (current_user.agents - [@agent]).find_all { |a| a.can_create_events? } %>
88 89
                 <%= f.select(:source_ids,
89 90
                              options_for_select(eventSources.map {|s| [s.name, s.id] },
90 91
                                                 @agent.source_ids),
91
-                             {}, { :multiple => true, :size => 5, :class => 'select2 form-control' }) %>
92
+                             {}, { :multiple => true, :size => 5, :class => 'select2-linked-tags form-control', data: {url_prefix: '/agents'} }) %>
92 93
                 <span class='cannot-receive-events text-info'>This type of Agent cannot receive events.</span>
93 94
                 <%= f.label :propagate_immediately, :class => 'propagate-immediately' do %>Propagate immediately
94 95
                   <%= f.check_box :propagate_immediately %>
@@ -98,13 +99,26 @@
98 99
               </div>
99 100
             </div>
100 101
 
102
+            <div class="form-group">
103
+              <%= f.label :receivers %>
104
+              <span class="glyphicon glyphicon-question-sign hover-help" data-content="Events created by this Agent will be sent to the selected Agents."></span>
105
+              <div class="event-related-region">
106
+                <% eventTargets = (current_user.agents - [@agent]).find_all { |a| a.can_receive_events? } %>
107
+                <%= f.select(:receiver_ids,
108
+                             options_for_select(eventTargets.map {|s| [s.name, s.id] },
109
+                                                @agent.receiver_ids),
110
+                             {}, { :multiple => true, :size => 5, :class => 'select2-linked-tags form-control', data: {url_prefix: '/agents'} }) %>
111
+                <span class='cannot-create-events text-info'>This type of Agent cannot create events.</span>
112
+              </div>
113
+            </div>
114
+
101 115
             <% if current_user.scenario_count > 0 %>
102 116
               <div class="form-group">
103 117
                 <%= f.label :scenarios %>
104 118
                 <span class="glyphicon glyphicon-question-sign hover-help" data-content="Use Scenarios to group sets of Agents, both for organization, and to make them easy to export and share."></span>
105 119
                 <%= f.select(:scenario_ids,
106 120
                              options_for_select(current_user.scenarios.pluck(:name, :id), @agent.scenario_ids),
107
-                             {}, { :multiple => true, :size => 5, :class => 'select2 form-control' }) %>
121
+                             {}, { :multiple => true, :size => 5, :class => 'select2-linked-tags form-control', data: {url_prefix: '/scenarios'} }) %>
108 122
               </div>
109 123
             <% end %>
110 124
 

+ 1 - 1
app/views/scenarios/_form.html.erb

@@ -53,7 +53,7 @@
53 53
           <%= f.label :agents %>
54 54
           <%= f.select(:agent_ids,
55 55
                        options_for_select(current_user.agents.pluck(:name, :id), @scenario.agent_ids),
56
-                       {}, { :multiple => true, :size => 5, :class => 'select2 form-control' }) %>
56
+                       {}, { :multiple => true, :size => 5, :class => 'select2-linked-tags form-control', data: {url_prefix: '/agents'} }) %>
57 57
         </div>
58 58
       </div>
59 59
     </div>

+ 1 - 1
config/locales/en.yml

@@ -40,4 +40,4 @@ en:
40 40
         other: ">%{count}yr"
41 41
       almost_x_years:
42 42
         one:   "~1yr"
43
-        other: "~%{count}yr"
43
+        other: "~%{count}yr"

+ 9 - 0
lib/tasks/rspec.rake

@@ -0,0 +1,9 @@
1
+if defined? RSpec
2
+  namespace :spec do
3
+    desc 'Run all specs in spec directory (exluding feature specs)'
4
+    RSpec::Core::RakeTask.new(:nofeatures) do |task|
5
+      ENV['RSPEC_TASK'] = 'spec:nofeatures'
6
+      task.exclude_pattern = "spec/features/**/*_spec.rb"
7
+    end
8
+  end
9
+end

+ 10 - 2
spec/capybara_helper.rb

@@ -15,11 +15,19 @@ Capybara.default_max_wait_time = CAPYBARA_TIMEOUT
15 15
 RSpec.configure do |config|
16 16
   config.include Warden::Test::Helpers
17 17
   config.include AlertConfirmer, type: :feature
18
-  config.before :suite do
18
+
19
+  config.before(:suite) do
19 20
     Warden.test_mode!
21
+    DatabaseCleaner.clean_with(:truncation)
22
+  end
23
+
24
+  config.before(:each) do |example|
25
+    DatabaseCleaner.strategy = example.metadata[:js] ? :truncation : :transaction
26
+    DatabaseCleaner.start
20 27
   end
21 28
 
22
-  config.after :each do
29
+  config.after(:each) do
30
+    DatabaseCleaner.clean
23 31
     Warden.test_reset!
24 32
   end
25 33
 end

+ 12 - 0
spec/controllers/agents_controller_spec.rb

@@ -203,6 +203,18 @@ describe AgentsController do
203 203
       expect(assigns(:agent)).to be_a(Agents::WebsiteAgent)
204 204
     end
205 205
 
206
+    it "creates Agents and accepts specifing a target agent" do
207
+      sign_in users(:bob)
208
+      attributes = valid_attributes
209
+      attributes[:receiver_ids] = attributes[:source_ids]
210
+      expect {
211
+        expect {
212
+          post :create, :agent => attributes
213
+        }.to change { users(:bob).agents.count }.by(1)
214
+      }.to change { Link.count }.by(2)
215
+      expect(assigns(:agent)).to be_a(Agents::WebsiteAgent)
216
+    end
217
+
206 218
     it "shows errors" do
207 219
       sign_in users(:bob)
208 220
       expect {

+ 1 - 1
spec/features/admin_users_spec.rb

@@ -1,4 +1,4 @@
1
-require 'capybara_helper'
1
+require 'rails_helper'
2 2
 
3 3
 describe Admin::UsersController do
4 4
   it "requires to be signed in as an admin" do

+ 68 - 3
spec/features/create_an_agent_spec.rb

@@ -1,8 +1,11 @@
1
-require 'capybara_helper'
1
+require 'rails_helper'
2 2
 
3 3
 describe "Creating a new agent", js: true do
4
-  it "creates an agent" do
4
+  before(:each) do
5 5
     login_as(users(:bob))
6
+  end
7
+
8
+  it "creates an agent" do
6 9
     visit "/"
7 10
     page.find("a", text: "Agents").trigger(:mouseover)
8 11
     click_on("New Agent")
@@ -15,7 +18,6 @@ describe "Creating a new agent", js: true do
15 18
   end
16 19
 
17 20
   it "creates an alert if a new agent with invalid json is submitted" do
18
-    login_as(users(:bob))
19 21
     visit "/"
20 22
     page.find("a", text: "Agents").trigger(:mouseover)
21 23
     click_on("New Agent")
@@ -30,4 +32,67 @@ describe "Creating a new agent", js: true do
30 32
     }')
31 33
     expect(get_alert_text_from { click_on "Save" }).to have_text("Sorry, there appears to be an error in your JSON input. Please fix it before continuing.")
32 34
   end
35
+
36
+  context "displaying the correct information" do
37
+    before(:each) do
38
+      visit new_agent_path
39
+    end
40
+    it "shows all options for agents that can be scheduled, create and receive events" do
41
+      select2("Website Agent", from: "Type")
42
+      expect(page).not_to have_content('This type of Agent cannot create events.')
43
+    end
44
+
45
+    it "does not show the target select2 field when the agent can not create events" do
46
+      select2("Growl Agent", from: "Type")
47
+      expect(page).to have_content('This type of Agent cannot create events.')
48
+    end
49
+  end
50
+
51
+  it "allows to click on on the agent name in select2 tags" do
52
+    agent = agents(:bob_weather_agent)
53
+    visit new_agent_path
54
+    select2("Website Agent", from: "Type")
55
+    select2("SF Weather", from: 'Sources')
56
+    click_on "SF Weather"
57
+    expect(page).to have_content "Editing your WeatherAgent"
58
+  end
59
+
60
+  context "clearing unsupported fields of agents" do
61
+    before do
62
+      visit new_agent_path
63
+    end
64
+
65
+    it "does not send previously configured sources when the current agent does not support them" do
66
+      select2("Website Agent", from: "Type")
67
+      select2("SF Weather", from: 'Sources')
68
+      select2("Webhook Agent", from: "Type")
69
+      fill_in(:agent_name, with: "No sources")
70
+      click_on "Save"
71
+      expect(page).to have_content("No sources")
72
+      agent = Agent.find_by(name: "No sources")
73
+      expect(agent.sources).to eq([])
74
+    end
75
+
76
+    it "does not send previously configured control targets when the current agent does not support them" do
77
+      select2("Commander Agent", from: "Type")
78
+      select2("SF Weather", from: 'Control targets')
79
+      select2("Webhook Agent", from: "Type")
80
+      fill_in(:agent_name, with: "No control targets")
81
+      click_on "Save"
82
+      expect(page).to have_content("No control targets")
83
+      agent = Agent.find_by(name: "No control targets")
84
+      expect(agent.control_targets).to eq([])
85
+    end
86
+
87
+    it "does not send previously configured receivers when the current agent does not support them" do
88
+      select2("Website Agent", from: "Type")
89
+      select2("ZKCD", from: 'Receivers')
90
+      select2("Email Agent", from: "Type")
91
+      fill_in(:agent_name, with: "No receivers")
92
+      click_on "Save"
93
+      expect(page).to have_content("No receivers")
94
+      agent = Agent.find_by(name: "No receivers")
95
+      expect(agent.receivers).to eq([])
96
+    end
97
+  end
33 98
 end

+ 1 - 1
spec/features/edit_an_agent_spec.rb

@@ -1,4 +1,4 @@
1
-require 'capybara_helper'
1
+require 'rails_helper'
2 2
 
3 3
 describe "Editing an agent", js: true do
4 4
   it "creates an alert if a agent with invalid json is submitted" do

+ 1 - 1
spec/fixtures/agents.yml

@@ -38,7 +38,7 @@ bob_disabled_website_agent:
38 38
   user: bob
39 39
   events_count: 1
40 40
   schedule: "midnight"
41
-  name: "Disabled ZKCD"
41
+  name: "Disabled Agent"
42 42
   guid: <%= SecureRandom.hex %>
43 43
   options: <%= {
44 44
                  :url => "http://xkcd.com",

+ 2 - 0
spec/helpers/dot_helper_spec.rb

@@ -51,6 +51,8 @@ describe DotHelper do
51 51
             agent.save!
52 52
           },
53 53
         ]
54
+        @foo.reload
55
+        @bar2.reload
54 56
       end
55 57
 
56 58
       it "generates a DOT script" do

+ 13 - 0
spec/models/agent_spec.rb

@@ -546,6 +546,17 @@ describe Agent do
546 546
         expect(agent).to have(0).errors_on(:sources)
547 547
       end
548 548
 
549
+      it "should not allow target agents owned by other people" do
550
+        agent = Agents::SomethingSource.new(:name => "something")
551
+        agent.user = users(:bob)
552
+        agent.receiver_ids = [agents(:bob_weather_agent).id]
553
+        expect(agent).to have(0).errors_on(:receivers)
554
+        agent.receiver_ids = [agents(:jane_weather_agent).id]
555
+        expect(agent).to have(1).errors_on(:receivers)
556
+        agent.user = users(:jane)
557
+        expect(agent).to have(0).errors_on(:receivers)
558
+      end
559
+
549 560
       it "should not allow controller agents owned by other people" do
550 561
         agent = Agents::SomethingSource.new(:name => "something")
551 562
         agent.user = users(:bob)
@@ -961,6 +972,8 @@ describe AgentDrop do
961 972
     @efa.sources << @wsa1 << @wsa2
962 973
     @efa.memory[:test] = 1
963 974
     @efa.save!
975
+    @wsa1.reload
976
+    @wsa2.reload
964 977
   end
965 978
 
966 979
   it 'should be created via Agent#to_liquid' do

+ 5 - 1
spec/rails_helper.rb

@@ -38,7 +38,7 @@ RSpec.configure do |config|
38 38
   # If you're not using ActiveRecord, or you'd prefer not to run each of your
39 39
   # examples within a transaction, remove the following line or assign false
40 40
   # instead of true.
41
-  config.use_transactional_fixtures = true
41
+  config.use_transactional_fixtures = ENV['RSPEC_TASK'] == 'spec:nofeatures'
42 42
 
43 43
   # rspec-rails 3 will no longer automatically infer an example group's spec type
44 44
   # from the file location. You can explicitly opt-in to this feature using this
@@ -70,3 +70,7 @@ RSpec.configure do |config|
70 70
   config.include SpecHelpers
71 71
   config.include Delorean
72 72
 end
73
+
74
+if ENV['RSPEC_TASK'] != 'spec:nofeatures'
75
+  require 'capybara_helper'
76
+end