detour 0.0.3 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +2 -25
  3. data/app/assets/javascripts/detour/add_fields.js +7 -0
  4. data/app/assets/javascripts/detour/delete_feature.js +9 -11
  5. data/app/assets/javascripts/detour/delete_flag.js +9 -11
  6. data/app/assets/javascripts/detour/delete_group.js +5 -0
  7. data/app/assets/javascripts/detour/feature_lines.js +23 -0
  8. data/app/assets/javascripts/detour/modals.js +1 -0
  9. data/app/assets/stylesheets/detour/main.css +12 -0
  10. data/app/controllers/detour/features_controller.rb +3 -2
  11. data/app/controllers/detour/flaggable_flags_controller.rb +9 -77
  12. data/app/controllers/detour/groups_controller.rb +39 -0
  13. data/app/helpers/detour/application_helper.rb +11 -0
  14. data/app/helpers/detour/flaggable_flags_helper.rb +20 -0
  15. data/app/helpers/detour/flags_helper.rb +5 -1
  16. data/app/models/detour/concerns/keepable.rb +21 -0
  17. data/app/models/detour/concerns/matchers.rb +28 -9
  18. data/app/models/detour/database_group_flag.rb +30 -0
  19. data/app/models/detour/defined_group.rb +21 -0
  20. data/app/models/detour/defined_group_flag.rb +28 -0
  21. data/app/models/detour/feature.rb +4 -3
  22. data/app/models/detour/flag_in_flag.rb +1 -8
  23. data/app/models/detour/flaggable_flag.rb +24 -0
  24. data/app/models/detour/group.rb +17 -0
  25. data/app/models/detour/membership.rb +41 -0
  26. data/app/models/detour/opt_out_flag.rb +1 -8
  27. data/app/views/detour/flaggable_flags/_flaggable_flag_fields.html.erb +19 -0
  28. data/app/views/detour/flaggable_flags/index.html.erb +13 -26
  29. data/app/views/detour/flags/_feature_form.html.erb +12 -3
  30. data/app/views/detour/flags/index.html.erb +7 -2
  31. data/app/views/detour/groups/_group.html.erb +3 -0
  32. data/app/views/detour/groups/_membership_fields.html.erb +19 -0
  33. data/app/views/detour/groups/index.html.erb +21 -0
  34. data/app/views/detour/groups/show.html.erb +41 -0
  35. data/app/views/detour/memberships/_membership.html.erb +4 -0
  36. data/app/views/detour/{features → shared}/_errors.html.erb +2 -2
  37. data/app/views/detour/shared/_nav.html.erb +1 -0
  38. data/app/views/detour/shared/error.js.erb +5 -0
  39. data/config/locales/en.yml +11 -0
  40. data/config/routes.rb +8 -7
  41. data/detour.gemspec +1 -0
  42. data/lib/detour/acts_as_flaggable.rb +19 -4
  43. data/lib/detour/configuration.rb +1 -1
  44. data/lib/detour/flag_form.rb +53 -34
  45. data/lib/detour/flaggable.rb +0 -19
  46. data/lib/detour/version.rb +1 -1
  47. data/lib/generators/templates/migration.rb +21 -1
  48. data/lib/tasks/.gitkeep +0 -0
  49. data/spec/controllers/detour/flaggable_flags_controller_spec.rb +30 -67
  50. data/spec/controllers/detour/groups_controller_spec.rb +107 -0
  51. data/spec/dummy/db/migrate/20131221052201_setup_detour.rb +21 -1
  52. data/spec/dummy/db/schema.rb +20 -1
  53. data/spec/factories/database_group_flag.rb +7 -0
  54. data/spec/factories/{group_flag.rb → defined_group_flag.rb} +1 -1
  55. data/spec/factories/group.rb +10 -0
  56. data/spec/factories/membership.rb +6 -0
  57. data/spec/features/database_group_flags_spec.rb +50 -0
  58. data/spec/features/database_groups_spec.rb +174 -0
  59. data/spec/features/defined_group_flags_spec.rb +67 -0
  60. data/spec/features/features_spec.rb +44 -0
  61. data/spec/features/flag_in_flags_spec.rb +22 -60
  62. data/spec/features/opt_out_flags_spec.rb +34 -59
  63. data/spec/integration/group_rollout_spec.rb +2 -2
  64. data/spec/lib/detour/acts_as_flaggable_spec.rb +12 -3
  65. data/spec/lib/detour/configuration_spec.rb +6 -2
  66. data/spec/lib/detour/flag_form_spec.rb +0 -11
  67. data/spec/lib/detour/flaggable_spec.rb +1 -54
  68. data/spec/models/detour/database_group_flag_spec.rb +29 -0
  69. data/spec/models/detour/defined_group_spec.rb +21 -0
  70. data/spec/models/detour/feature_spec.rb +57 -119
  71. data/spec/models/detour/flag_in_flag_spec.rb +1 -4
  72. data/spec/models/detour/flaggable_flag_spec.rb +25 -0
  73. data/spec/models/detour/group_flag_spec.rb +1 -1
  74. data/spec/models/detour/membership_spec.rb +58 -0
  75. data/spec/models/detour/opt_out_flag_spec.rb +1 -4
  76. data/spec/spec_helper.rb +4 -0
  77. metadata +97 -81
  78. data/app/models/detour/concerns/flag_actions.rb +0 -141
  79. data/app/models/detour/group_flag.rb +0 -13
  80. data/app/views/detour/features/_success.html.erb +0 -1
  81. data/app/views/detour/features/error.js.erb +0 -5
  82. data/lib/tasks/detour.rake +0 -119
  83. data/spec/features/group_flags_spec.rb +0 -49
  84. data/spec/integration/flag_rollout_spec.rb +0 -27
  85. data/spec/lib/tasks/detour_spec.rb +0 -162
  86. /data/app/views/detour/{features → shared}/success.js.erb +0 -0
@@ -10,8 +10,8 @@ describe Detour::FlaggableFlagsController do
10
10
  get :index, feature_name: flag.feature.name, flaggable_type: "users"
11
11
  end
12
12
 
13
- it "assigns the flag-in flags" do
14
- assigns(:flags).should eq [flag]
13
+ it "assigns the feature" do
14
+ assigns(:feature).should eq flag.feature
15
15
  end
16
16
 
17
17
  it "renders the index template" do
@@ -19,82 +19,45 @@ describe Detour::FlaggableFlagsController do
19
19
  end
20
20
  end
21
21
 
22
- describe "POST #create" do
23
- let!(:user) { create :user }
24
- let(:feature) { create :feature }
25
-
26
- context "when creating multiple flag-ins" do
27
- let!(:user2) { create :user, email: "another@example.com" }
28
-
29
- before do
30
- post :create, feature_name: feature.name, flaggable_type: user.class.table_name, ids: ids, format: :js
31
- end
22
+ describe "PUT #update" do
23
+ let(:flag) { create :flag_in_flag }
32
24
 
33
- context "when successful" do
34
- let(:ids) { [user.id.to_s, user2.id.to_s].join(",") }
25
+ before do
26
+ put :update, feature_name: flag.feature.name, flaggable_type: "users", feature: flag_params
27
+ end
35
28
 
36
- it "creates the flag-in" do
37
- feature.users_flag_ins.collect(&:flaggable).should eq [user, user2]
38
- end
29
+ context "when successful" do
30
+ let(:user) { create :user }
39
31
 
40
- it "sets a flash message" do
41
- flash[:notice].should eq "#{user.class.to_s.pluralize} #{user.id}, #{user2.id} have been flagged in to #{feature.name}"
42
- end
32
+ let(:flag_params) do
33
+ {
34
+ users_flag_ins_attributes: {
35
+ "1" => { flaggable_type: "User", flaggable_key: user.id, _destroy: 0 }
36
+ }
37
+ }
43
38
  end
44
39
 
45
- context "when unsuccessful" do
46
- let(:ids) { "foo" }
47
-
48
- it "renders the errors template" do
49
- response.should render_template "error"
50
- end
40
+ it "sets a flash message" do
41
+ flash[:notice].should eq "Your flag-ins have been updated"
51
42
  end
52
43
 
53
- context "when creating a single flag-in" do
54
- before do
55
- post :create, feature_name: feature.name, flaggable_type: user.class.table_name, ids: ids, format: :js
56
- end
57
-
58
- context "when successful" do
59
- let(:ids) { user.id.to_s }
60
-
61
- it "creates the flag-in" do
62
- feature.users_flag_ins.collect(&:flaggable).should eq [user]
63
- end
64
-
65
- it "sets a flash message" do
66
- flash[:notice].should eq "#{user.class} #{user.id} has been flagged in to #{feature.name}"
67
- end
68
- end
69
-
70
- context "when the flaggable can't be found" do
71
- let(:ids) { "foo" }
72
-
73
- it "renders the errors template" do
74
- response.should render_template "error"
75
- end
76
- end
44
+ it "redirect to the group" do
45
+ response.should redirect_to flag_in_flags_path(feature_name: flag.feature.name, flaggable_type: "users")
77
46
  end
78
47
  end
79
- end
80
-
81
- describe "DELETE #destroy" do
82
- let(:flag) { create :flag_in_flag }
83
-
84
- before do
85
- delete :destroy, feature_name: flag.feature.name, flaggable_type: "users", id: flag.id
86
- end
87
48
 
88
- it "destroys the flag" do
89
- expect { flag.reload }.to raise_error ActiveRecord::RecordNotFound
90
- end
91
-
92
- it "sets a flash message" do
93
- flash[:notice].should eq "#{flag.feature.name} flag-in for User #{flag.flaggable.id} has been deleted."
94
- end
49
+ context "when unsuccessful" do
50
+ let(:flag_params) do
51
+ {
52
+ users_flag_ins_attributes: {
53
+ "1" => { flaggable_type: "User", flaggable_key: nil, _destroy: 0 }
54
+ }
55
+ }
56
+ end
95
57
 
96
- it "redirects to the flag-ins index" do
97
- response.should redirect_to flag_in_flags_path flag.feature.name, "users"
58
+ it "renders the show template" do
59
+ response.should render_template :index
60
+ end
98
61
  end
99
62
  end
100
63
  end
@@ -0,0 +1,107 @@
1
+ require "spec_helper"
2
+
3
+ describe Detour::GroupsController do
4
+ routes { Detour::Engine.routes }
5
+
6
+ describe "GET #index" do
7
+ let!(:group) { create :group }
8
+
9
+ before do
10
+ get :index
11
+ end
12
+
13
+ it "assigns the groups" do
14
+ assigns(:groups).should eq [group]
15
+ end
16
+
17
+ it "renders the index template" do
18
+ response.should render_template "groups/index"
19
+ end
20
+ end
21
+
22
+ describe "GET #show" do
23
+ let!(:group) { create :group }
24
+
25
+ before do
26
+ get :show, id: group.to_param
27
+ end
28
+
29
+ it "assigns the groups" do
30
+ assigns(:group).should eq group
31
+ end
32
+
33
+ it "renders the show template" do
34
+ response.should render_template "groups/show"
35
+ end
36
+ end
37
+
38
+ describe "POST #create" do
39
+ before do
40
+ post :create, format: :js, group: group_params
41
+ end
42
+
43
+ context "when successful" do
44
+ let(:group_params) { { name: "Foo Group", flaggable_type: "User" } }
45
+
46
+ it "sets a flash message" do
47
+ flash[:notice].should eq "Your group has been successfully created."
48
+ end
49
+
50
+ it "renders the success template" do
51
+ response.should render_template "success"
52
+ end
53
+ end
54
+
55
+ context "when unsuccessful" do
56
+ let(:group_params) { { name: "" } }
57
+
58
+ it "renders the errors template" do
59
+ response.should render_template "error"
60
+ end
61
+ end
62
+ end
63
+
64
+ describe "PUT #update" do
65
+ let(:group) { create :group }
66
+
67
+ before do
68
+ put :update, id: group.to_param, group: group_params
69
+ end
70
+
71
+ context "when successful" do
72
+ let(:group_params) { { name: "New Group Name" } }
73
+
74
+ it "sets a flash message" do
75
+ flash[:notice].should eq "Your group has been successfully updated."
76
+ end
77
+
78
+ it "redirect to the group" do
79
+ response.should redirect_to group_path group
80
+ end
81
+ end
82
+
83
+ context "when unsuccessful" do
84
+ let(:group_params) { { name: "" } }
85
+
86
+ it "renders the show template" do
87
+ response.should render_template "show"
88
+ end
89
+ end
90
+ end
91
+
92
+ describe "DELETE #destroy" do
93
+ let(:group) { create :group }
94
+
95
+ before do
96
+ delete :destroy, id: group.to_param
97
+ end
98
+
99
+ it "sets a flash message" do
100
+ flash[:notice].should eq "Group \"#{group.name}\" has been deleted."
101
+ end
102
+
103
+ it "redirects to the groups path" do
104
+ response.should redirect_to groups_path
105
+ end
106
+ end
107
+ end
@@ -2,7 +2,6 @@ class SetupDetour < ActiveRecord::Migration
2
2
  def change
3
3
  create_table :detour_features do |t|
4
4
  t.string :name
5
- t.integer :failure_count, default: 0
6
5
  t.text :flag_in_counts, default: "{}"
7
6
  t.text :opt_out_counts, default: "{}"
8
7
  t.timestamps
@@ -15,6 +14,7 @@ class SetupDetour < ActiveRecord::Migration
15
14
  t.integer :feature_id
16
15
  t.integer :flaggable_id
17
16
  t.string :flaggable_type
17
+ t.integer :group_id
18
18
  t.string :group_name
19
19
  t.integer :percentage
20
20
  t.timestamps
@@ -22,11 +22,31 @@ class SetupDetour < ActiveRecord::Migration
22
22
 
23
23
  add_index :detour_flags, :type
24
24
  add_index :detour_flags, :feature_id
25
+ add_index :detour_flags, :group_id
26
+ add_index :detour_flags,
27
+ [:type, :feature_id, :group_id]
25
28
  add_index :detour_flags,
26
29
  [:type, :feature_id, :flaggable_type, :flaggable_id],
27
30
  name: "flag_type_feature_flaggable_type_id"
28
31
  add_index :detour_flags,
29
32
  [:type, :feature_id, :flaggable_type],
30
33
  name: "flag_type_feature_flaggable_type"
34
+
35
+ create_table :detour_groups do |t|
36
+ t.string :name
37
+ t.string :flaggable_type
38
+ t.timestamps
39
+ end
40
+
41
+ create_table :detour_memberships do |t|
42
+ t.integer :group_id
43
+ t.string :member_type
44
+ t.integer :member_id
45
+ t.timestamps
46
+ end
47
+
48
+ add_index :detour_memberships, [:group_id, :member_type, :member_id],
49
+ name: :detour_memberships_membership_index,
50
+ unique: true
31
51
  end
32
52
  end
@@ -15,7 +15,6 @@ ActiveRecord::Schema.define(:version => 20131221052201) do
15
15
 
16
16
  create_table "detour_features", :force => true do |t|
17
17
  t.string "name"
18
- t.integer "failure_count", :default => 0
19
18
  t.text "flag_in_counts", :default => "{}"
20
19
  t.text "opt_out_counts", :default => "{}"
21
20
  t.datetime "created_at", :null => false
@@ -29,6 +28,7 @@ ActiveRecord::Schema.define(:version => 20131221052201) do
29
28
  t.integer "feature_id"
30
29
  t.integer "flaggable_id"
31
30
  t.string "flaggable_type"
31
+ t.integer "group_id"
32
32
  t.string "group_name"
33
33
  t.integer "percentage"
34
34
  t.datetime "created_at", :null => false
@@ -36,10 +36,29 @@ ActiveRecord::Schema.define(:version => 20131221052201) do
36
36
  end
37
37
 
38
38
  add_index "detour_flags", ["feature_id"], :name => "index_detour_flags_on_feature_id"
39
+ add_index "detour_flags", ["group_id"], :name => "index_detour_flags_on_group_id"
39
40
  add_index "detour_flags", ["type", "feature_id", "flaggable_type", "flaggable_id"], :name => "flag_type_feature_flaggable_type_id"
40
41
  add_index "detour_flags", ["type", "feature_id", "flaggable_type"], :name => "flag_type_feature_flaggable_type"
42
+ add_index "detour_flags", ["type", "feature_id", "group_id"], :name => "index_detour_flags_on_type_and_feature_id_and_group_id"
41
43
  add_index "detour_flags", ["type"], :name => "index_detour_flags_on_type"
42
44
 
45
+ create_table "detour_groups", :force => true do |t|
46
+ t.string "name"
47
+ t.string "flaggable_type"
48
+ t.datetime "created_at", :null => false
49
+ t.datetime "updated_at", :null => false
50
+ end
51
+
52
+ create_table "detour_memberships", :force => true do |t|
53
+ t.integer "group_id"
54
+ t.string "member_type"
55
+ t.integer "member_id"
56
+ t.datetime "created_at", :null => false
57
+ t.datetime "updated_at", :null => false
58
+ end
59
+
60
+ add_index "detour_memberships", ["group_id", "member_type", "member_id"], :name => "detour_memberships_membership_index", :unique => true
61
+
43
62
  create_table "users", :force => true do |t|
44
63
  t.string "email"
45
64
  t.string "name"
@@ -0,0 +1,7 @@
1
+ FactoryGirl.define do
2
+ factory :database_group_flag, class: "Detour::DatabaseGroupFlag" do
3
+ feature
4
+ flaggable_type "User"
5
+ group
6
+ end
7
+ end
@@ -1,5 +1,5 @@
1
1
  FactoryGirl.define do
2
- factory :group_flag, class: "Detour::GroupFlag" do
2
+ factory :defined_group_flag, class: "Detour::DefinedGroupFlag" do
3
3
  feature
4
4
  flaggable_type "User"
5
5
  group_name "foo users"
@@ -0,0 +1,10 @@
1
+ FactoryGirl.define do
2
+ sequence :name do |n|
3
+ "Group #{n}"
4
+ end
5
+
6
+ factory :group, class: "Detour::Group" do
7
+ flaggable_type "User"
8
+ name
9
+ end
10
+ end
@@ -0,0 +1,6 @@
1
+ FactoryGirl.define do
2
+ factory :membership, class: "Detour::Membership" do
3
+ association :member, factory: :user
4
+ group
5
+ end
6
+ end
@@ -0,0 +1,50 @@
1
+ require "spec_helper"
2
+
3
+ describe "creating database group flags" do
4
+ let!(:feature) { create :feature }
5
+ let!(:group) { create :group, flaggable_type: "User" }
6
+ let(:checkbox) { "features[#{feature.name}][users_database_group_flags_attributes[#{group.name}]][to_keep]" }
7
+
8
+ before do
9
+ visit "/detour/flags/users"
10
+ check checkbox
11
+ end
12
+
13
+ it "creates the database group flag" do
14
+ click_button "Save Changes"
15
+ feature.reload.users_database_group_flags.map(&:group).should eq [group]
16
+ end
17
+
18
+ context "when there are errors in other fields" do
19
+ it "preserves the database group flag option" do
20
+ fill_in "features[#{feature.name}][users_percentage_flag_attributes][percentage]", with: 101
21
+ click_button "Save Changes"
22
+ page.find("input[type='checkbox'][name='#{checkbox}']").should be_checked
23
+ end
24
+ end
25
+ end
26
+
27
+ describe "removing database group flags" do
28
+ let!(:feature) { create :feature }
29
+ let(:group) { create :group, flaggable_type: "User" }
30
+ let!(:group_flag) { create :database_group_flag, feature: feature, group: group, flaggable_type: "User" }
31
+ let(:checkbox) { "features[#{feature.name}][users_database_group_flags_attributes[#{group.name}]][to_keep]" }
32
+
33
+ before do
34
+ visit "/detour/flags/users"
35
+ uncheck checkbox
36
+ end
37
+
38
+ it "removes the database group flag" do
39
+ click_button "Save Changes"
40
+ feature.reload.users_database_group_flags.should be_empty
41
+ end
42
+
43
+ context "when there are errors in other fields" do
44
+ it "preserves the database group flag option" do
45
+ fill_in "features[#{feature.name}][users_percentage_flag_attributes][percentage]", with: 101
46
+ click_button "Save Changes"
47
+ page.find("input[type='checkbox'][name='#{checkbox}']").should_not be_checked
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,174 @@
1
+ require "spec_helper"
2
+
3
+ describe "listing groups" do
4
+ let!(:group) { create :group }
5
+
6
+ before do
7
+ visit "/detour/groups"
8
+ end
9
+
10
+ it "lists every group" do
11
+ within "ul li.group" do
12
+ page.should have_content group.name
13
+ end
14
+ end
15
+ end
16
+
17
+ describe "showing a group" do
18
+ let(:user) { create :user }
19
+ let(:group) { create :group }
20
+
21
+ before do
22
+ User.instance_variable_set "@detour_flaggable_find_by", :email
23
+ create :membership, group: group, member: user
24
+ visit "/detour/groups/#{group.to_param}"
25
+ end
26
+
27
+ it "lists every membership" do
28
+ page.find("input[name=member_identifier]").value.should eq user.email
29
+ end
30
+ end
31
+
32
+ describe "creating a group", js: true do
33
+ before do
34
+ visit "/detour/groups"
35
+ page.find("[data-target='#create-group']").click
36
+ end
37
+
38
+ context "when successful" do
39
+ before do
40
+ fill_in "group[name]", with: "New Group"
41
+ select "User", from: "group[flaggable_type]"
42
+ click_button "Create Group"
43
+ end
44
+
45
+ it "displays a flash message" do
46
+ page.should have_content "Your group has been successfully created."
47
+ end
48
+
49
+ it "shows the newly created group" do
50
+ within "ul li.group" do
51
+ page.should have_content "New Group"
52
+ end
53
+ end
54
+ end
55
+
56
+ context "when unsuccessful" do
57
+ before do
58
+ click_button "Create Group"
59
+ end
60
+
61
+ it "displays error messages" do
62
+ page.should have_content "Name can't be blank"
63
+ end
64
+ end
65
+ end
66
+
67
+ describe "updating a group" do
68
+ let(:group) { create :group }
69
+
70
+ before do
71
+ visit "/detour/groups/#{group.to_param}"
72
+ end
73
+
74
+ context "when successful" do
75
+ before do
76
+ fill_in "group[name]", with: "New Group Name"
77
+ click_button "Update Group"
78
+ end
79
+
80
+ it "displays a flash message" do
81
+ page.should have_content "Your group has been successfully updated."
82
+ end
83
+
84
+ it "shows the newly updated group" do
85
+ within "h1" do
86
+ page.should have_content "New Group Name"
87
+ end
88
+ end
89
+ end
90
+
91
+ context "when unsuccessful" do
92
+ before do
93
+ fill_in "group[name]", with: ""
94
+ click_button "Update Group"
95
+ end
96
+
97
+ it "displays error messages" do
98
+ page.should have_content "Name can't be blank"
99
+ end
100
+ end
101
+ end
102
+
103
+ describe "adding a member to a group", js: true do
104
+ let(:group) { create :group }
105
+ let!(:user) { create :user }
106
+
107
+ before do
108
+ User.instance_variable_set "@detour_flaggable_find_by", :email
109
+ visit "/detour/groups/#{group.to_param}"
110
+ page.find(".add-fields").click
111
+ end
112
+
113
+ context "when successful" do
114
+ before do
115
+ name = page.find("##{page.all("label")[-2][:for]}")[:name]
116
+ fill_in name, with: user.email
117
+ click_button "Update Group"
118
+ end
119
+
120
+ it "displays a flash message" do
121
+ page.should have_content "Your group has been successfully updated."
122
+ end
123
+
124
+ it "shows the newly added member" do
125
+ page.find("input[type='text'][disabled]").value.should eq user.email
126
+ end
127
+ end
128
+
129
+ context "when unsuccessful" do
130
+ before do
131
+ click_button "Update Group"
132
+ end
133
+
134
+ it "displays error messages" do
135
+ page.should have_content "Memberships user \"\" could not be found"
136
+ end
137
+ end
138
+ end
139
+
140
+ describe "removing a member from a group" do
141
+ let(:group) { create :group }
142
+ let(:user) { create :user }
143
+ let!(:membership) { create :membership, group: group, member: user }
144
+
145
+ before do
146
+ User.instance_variable_set "@detour_flaggable_find_by", :email
147
+ visit "/detour/groups/#{group.to_param}"
148
+ name = page.find("##{page.all("label").last[:for]}")[:name]
149
+ check name
150
+ click_button "Update Group"
151
+ end
152
+
153
+ it "does not show the removed member" do
154
+ page.should_not have_selector "label[for='group_memberships_attributes_0_member_key']"
155
+ end
156
+ end
157
+
158
+ describe "destroying a group", js: true do
159
+ let!(:group) { create :group }
160
+
161
+ before do
162
+ visit "/detour/groups/#{group.to_param}"
163
+ click_button "Delete Group"
164
+ page.find(".modal a").click
165
+ end
166
+
167
+ it "shows a flash message" do
168
+ page.should have_content "Group \"#{group.name}\" has been deleted"
169
+ end
170
+
171
+ it "shows the remaining groups" do
172
+ page.should_not have_selector ".group"
173
+ end
174
+ end
@@ -0,0 +1,67 @@
1
+ require "spec_helper"
2
+
3
+ describe "listing defined groups" do
4
+ before do
5
+ Detour.config.define_user_group :admins do |user|
6
+ end
7
+
8
+ visit "/detour/flags/users"
9
+ end
10
+
11
+ it "displays the defined groups" do
12
+ page.should have_content "admins"
13
+ end
14
+ end
15
+
16
+ describe "creating defined group flags" do
17
+ let!(:feature) { create :feature }
18
+ let(:checkbox) { "features[#{feature.name}][users_defined_group_flags_attributes[admins]][to_keep]" }
19
+
20
+ before do
21
+ Detour.config.define_user_group :admins do |user|
22
+ end
23
+
24
+ visit "/detour/flags/users"
25
+ check checkbox
26
+ end
27
+
28
+ it "creates the group flag" do
29
+ click_button "Save Changes"
30
+ feature.reload.users_defined_group_flags.first.group_name.should eq "admins"
31
+ end
32
+
33
+ context "when there are errors in other fields" do
34
+ it "preserves the database group flag option" do
35
+ fill_in "features[#{feature.name}][users_percentage_flag_attributes][percentage]", with: 101
36
+ click_button "Save Changes"
37
+ page.find("input[type='checkbox'][name='#{checkbox}']").should be_checked
38
+ end
39
+ end
40
+ end
41
+
42
+ describe "removing defined group flags" do
43
+ let(:feature) { create :feature }
44
+ let!(:group_flag) { create :defined_group_flag, feature: feature, group_name: "admins" }
45
+ let(:checkbox) { "features[#{feature.name}][users_defined_group_flags_attributes[admins]][to_keep]" }
46
+
47
+ before do
48
+ Detour.config.define_user_group :admins do |user|
49
+ end
50
+
51
+ visit "/detour/flags/users"
52
+ uncheck checkbox
53
+ end
54
+
55
+ it "creates the group flag" do
56
+ click_button "Save Changes"
57
+ feature.reload.users_defined_group_flags.should be_empty
58
+ end
59
+
60
+ context "when there are errors in other fields" do
61
+ it "preserves the database group flag option" do
62
+ fill_in "features[#{feature.name}][users_percentage_flag_attributes][percentage]", with: 101
63
+ click_button "Save Changes"
64
+ page.find("input[type='checkbox'][name='#{checkbox}']").should_not be_checked
65
+ end
66
+ end
67
+ end