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.
- checksums.yaml +7 -0
- data/README.md +2 -25
- data/app/assets/javascripts/detour/add_fields.js +7 -0
- data/app/assets/javascripts/detour/delete_feature.js +9 -11
- data/app/assets/javascripts/detour/delete_flag.js +9 -11
- data/app/assets/javascripts/detour/delete_group.js +5 -0
- data/app/assets/javascripts/detour/feature_lines.js +23 -0
- data/app/assets/javascripts/detour/modals.js +1 -0
- data/app/assets/stylesheets/detour/main.css +12 -0
- data/app/controllers/detour/features_controller.rb +3 -2
- data/app/controllers/detour/flaggable_flags_controller.rb +9 -77
- data/app/controllers/detour/groups_controller.rb +39 -0
- data/app/helpers/detour/application_helper.rb +11 -0
- data/app/helpers/detour/flaggable_flags_helper.rb +20 -0
- data/app/helpers/detour/flags_helper.rb +5 -1
- data/app/models/detour/concerns/keepable.rb +21 -0
- data/app/models/detour/concerns/matchers.rb +28 -9
- data/app/models/detour/database_group_flag.rb +30 -0
- data/app/models/detour/defined_group.rb +21 -0
- data/app/models/detour/defined_group_flag.rb +28 -0
- data/app/models/detour/feature.rb +4 -3
- data/app/models/detour/flag_in_flag.rb +1 -8
- data/app/models/detour/flaggable_flag.rb +24 -0
- data/app/models/detour/group.rb +17 -0
- data/app/models/detour/membership.rb +41 -0
- data/app/models/detour/opt_out_flag.rb +1 -8
- data/app/views/detour/flaggable_flags/_flaggable_flag_fields.html.erb +19 -0
- data/app/views/detour/flaggable_flags/index.html.erb +13 -26
- data/app/views/detour/flags/_feature_form.html.erb +12 -3
- data/app/views/detour/flags/index.html.erb +7 -2
- data/app/views/detour/groups/_group.html.erb +3 -0
- data/app/views/detour/groups/_membership_fields.html.erb +19 -0
- data/app/views/detour/groups/index.html.erb +21 -0
- data/app/views/detour/groups/show.html.erb +41 -0
- data/app/views/detour/memberships/_membership.html.erb +4 -0
- data/app/views/detour/{features → shared}/_errors.html.erb +2 -2
- data/app/views/detour/shared/_nav.html.erb +1 -0
- data/app/views/detour/shared/error.js.erb +5 -0
- data/config/locales/en.yml +11 -0
- data/config/routes.rb +8 -7
- data/detour.gemspec +1 -0
- data/lib/detour/acts_as_flaggable.rb +19 -4
- data/lib/detour/configuration.rb +1 -1
- data/lib/detour/flag_form.rb +53 -34
- data/lib/detour/flaggable.rb +0 -19
- data/lib/detour/version.rb +1 -1
- data/lib/generators/templates/migration.rb +21 -1
- data/lib/tasks/.gitkeep +0 -0
- data/spec/controllers/detour/flaggable_flags_controller_spec.rb +30 -67
- data/spec/controllers/detour/groups_controller_spec.rb +107 -0
- data/spec/dummy/db/migrate/20131221052201_setup_detour.rb +21 -1
- data/spec/dummy/db/schema.rb +20 -1
- data/spec/factories/database_group_flag.rb +7 -0
- data/spec/factories/{group_flag.rb → defined_group_flag.rb} +1 -1
- data/spec/factories/group.rb +10 -0
- data/spec/factories/membership.rb +6 -0
- data/spec/features/database_group_flags_spec.rb +50 -0
- data/spec/features/database_groups_spec.rb +174 -0
- data/spec/features/defined_group_flags_spec.rb +67 -0
- data/spec/features/features_spec.rb +44 -0
- data/spec/features/flag_in_flags_spec.rb +22 -60
- data/spec/features/opt_out_flags_spec.rb +34 -59
- data/spec/integration/group_rollout_spec.rb +2 -2
- data/spec/lib/detour/acts_as_flaggable_spec.rb +12 -3
- data/spec/lib/detour/configuration_spec.rb +6 -2
- data/spec/lib/detour/flag_form_spec.rb +0 -11
- data/spec/lib/detour/flaggable_spec.rb +1 -54
- data/spec/models/detour/database_group_flag_spec.rb +29 -0
- data/spec/models/detour/defined_group_spec.rb +21 -0
- data/spec/models/detour/feature_spec.rb +57 -119
- data/spec/models/detour/flag_in_flag_spec.rb +1 -4
- data/spec/models/detour/flaggable_flag_spec.rb +25 -0
- data/spec/models/detour/group_flag_spec.rb +1 -1
- data/spec/models/detour/membership_spec.rb +58 -0
- data/spec/models/detour/opt_out_flag_spec.rb +1 -4
- data/spec/spec_helper.rb +4 -0
- metadata +97 -81
- data/app/models/detour/concerns/flag_actions.rb +0 -141
- data/app/models/detour/group_flag.rb +0 -13
- data/app/views/detour/features/_success.html.erb +0 -1
- data/app/views/detour/features/error.js.erb +0 -5
- data/lib/tasks/detour.rake +0 -119
- data/spec/features/group_flags_spec.rb +0 -49
- data/spec/integration/flag_rollout_spec.rb +0 -27
- data/spec/lib/tasks/detour_spec.rb +0 -162
- /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
|
14
|
-
assigns(:
|
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 "
|
23
|
-
let
|
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
|
-
|
34
|
-
|
25
|
+
before do
|
26
|
+
put :update, feature_name: flag.feature.name, flaggable_type: "users", feature: flag_params
|
27
|
+
end
|
35
28
|
|
36
|
-
|
37
|
-
|
38
|
-
end
|
29
|
+
context "when successful" do
|
30
|
+
let(:user) { create :user }
|
39
31
|
|
40
|
-
|
41
|
-
|
42
|
-
|
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
|
-
|
46
|
-
|
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
|
-
|
54
|
-
|
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
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
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
|
-
|
97
|
-
|
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
|
data/spec/dummy/db/schema.rb
CHANGED
@@ -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,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
|