sapling 0.0.1 → 0.1.0
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.
- data/.gitignore +2 -0
- data/lib/sapling.rb +1 -0
- data/lib/sapling/active_record.rb +32 -10
- data/lib/sapling/generators/css_generator.rb +31 -0
- data/lib/sapling/memory.rb +14 -7
- data/lib/sapling/rails.rb +17 -0
- data/lib/sapling/rails/action_controller.rb +23 -0
- data/lib/sapling/rails/controllers/sapling_controller.rb +7 -0
- data/lib/sapling/rails/railtie.rb +7 -0
- data/lib/sapling/rails/view_helpers.rb +22 -0
- data/lib/sapling/util.rb +9 -11
- data/lib/sapling/version.rb +1 -1
- data/rails/init.rb +2 -0
- data/sapling.gemspec +4 -3
- data/spec/active_record_spec.rb +0 -26
- data/spec/css_generator_spec.rb +47 -0
- data/spec/memory_feature_spec.rb +2 -2
- data/spec/memory_spec.rb +0 -26
- data/spec/rails_app/README +243 -0
- data/spec/rails_app/Rakefile +10 -0
- data/spec/rails_app/app/controllers/application_controller.rb +20 -0
- data/spec/rails_app/app/controllers/spaceman_spiffs_controller.rb +90 -0
- data/spec/rails_app/app/controllers/user_sessions_controller.rb +14 -0
- data/spec/rails_app/app/helpers/application_helper.rb +3 -0
- data/spec/rails_app/app/helpers/spaceman_spiffs_helper.rb +2 -0
- data/spec/rails_app/app/models/spaceman_spiff.rb +2 -0
- data/spec/rails_app/app/models/user.rb +3 -0
- data/spec/rails_app/app/views/layouts/spaceman_spiffs.html.erb +18 -0
- data/spec/rails_app/app/views/spaceman_spiffs/edit.html.erb +16 -0
- data/spec/rails_app/app/views/spaceman_spiffs/index.html.erb +21 -0
- data/spec/rails_app/app/views/spaceman_spiffs/multiple_features.html.erb +7 -0
- data/spec/rails_app/app/views/spaceman_spiffs/new.html.erb +15 -0
- data/spec/rails_app/app/views/spaceman_spiffs/show.html.erb +8 -0
- data/spec/rails_app/config/boot.rb +114 -0
- data/spec/rails_app/config/database.yml +17 -0
- data/spec/rails_app/config/environment.rb +48 -0
- data/spec/rails_app/config/environments/development.rb +17 -0
- data/spec/rails_app/config/environments/production.rb +28 -0
- data/spec/rails_app/config/environments/test.rb +28 -0
- data/spec/rails_app/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/rails_app/config/initializers/cookie_verification_secret.rb +7 -0
- data/spec/rails_app/config/initializers/inflections.rb +10 -0
- data/spec/rails_app/config/initializers/mime_types.rb +5 -0
- data/spec/rails_app/config/initializers/new_rails_defaults.rb +21 -0
- data/spec/rails_app/config/initializers/session_store.rb +15 -0
- data/spec/rails_app/config/locales/en.yml +5 -0
- data/spec/rails_app/config/routes.rb +48 -0
- data/spec/rails_app/db/migrate/20111207234232_create_spaceman_spiffs.rb +13 -0
- data/spec/rails_app/db/migrate/20111208003900_create_users.rb +13 -0
- data/spec/rails_app/db/migrate/20111208004048_add_sapling_settings.rb +13 -0
- data/spec/rails_app/db/schema.rb +32 -0
- data/spec/rails_app/db/seeds.rb +7 -0
- data/spec/rails_app/doc/README_FOR_APP +2 -0
- data/spec/rails_app/public/404.html +30 -0
- data/spec/rails_app/public/422.html +30 -0
- data/spec/rails_app/public/500.html +30 -0
- data/spec/rails_app/public/favicon.ico +0 -0
- data/spec/rails_app/public/images/rails.png +0 -0
- data/spec/rails_app/public/javascripts/application.js +2 -0
- data/spec/rails_app/public/javascripts/controls.js +963 -0
- data/spec/rails_app/public/javascripts/dragdrop.js +973 -0
- data/spec/rails_app/public/javascripts/effects.js +1128 -0
- data/spec/rails_app/public/javascripts/prototype.js +4320 -0
- data/spec/rails_app/public/robots.txt +5 -0
- data/spec/rails_app/public/stylesheets/scaffold.css +54 -0
- data/spec/rails_app/script/about +4 -0
- data/spec/rails_app/script/console +3 -0
- data/spec/rails_app/script/dbconsole +3 -0
- data/spec/rails_app/script/destroy +3 -0
- data/spec/rails_app/script/generate +3 -0
- data/spec/rails_app/script/performance/benchmarker +3 -0
- data/spec/rails_app/script/performance/profiler +3 -0
- data/spec/rails_app/script/plugin +3 -0
- data/spec/rails_app/script/runner +3 -0
- data/spec/rails_app/script/server +3 -0
- data/spec/rails_app/test/fixtures/sapling_settings.yml +9 -0
- data/spec/rails_app/test/fixtures/spaceman_spiffs.yml +7 -0
- data/spec/rails_app/test/fixtures/users.yml +7 -0
- data/spec/rails_app/test/integration/feature_test.rb +30 -0
- data/spec/rails_app/test/performance/browsing_test.rb +9 -0
- data/spec/rails_app/test/test_helper.rb +38 -0
- data/spec/rails_app/test/unit/helpers/spaceman_spiffs_helper_test.rb +4 -0
- data/spec/rails_app/test/unit/spaceman_spiff_test.rb +8 -0
- data/spec/rails_app/test/unit/user_test.rb +8 -0
- data/spec/sapling_examples.rb +88 -6
- metadata +181 -25
data/.gitignore
CHANGED
data/lib/sapling.rb
CHANGED
|
@@ -5,18 +5,40 @@ module Sapling
|
|
|
5
5
|
Model.table_name
|
|
6
6
|
end
|
|
7
7
|
|
|
8
|
+
private
|
|
9
|
+
def query_conditions(feature,normalized_options={})
|
|
10
|
+
ret=[
|
|
11
|
+
"#{'feature = ? AND ' if feature} ((user_id IS NOT NULL AND user_id = ?) OR (percentage IS NOT NULL AND ? < percentage)) "
|
|
12
|
+
]
|
|
13
|
+
ret<<feature.to_s if feature
|
|
14
|
+
ret+=[
|
|
15
|
+
normalized_options[:user_id],
|
|
16
|
+
Util::modded_context_id(normalized_options)
|
|
17
|
+
]
|
|
18
|
+
ret
|
|
19
|
+
end
|
|
20
|
+
public
|
|
21
|
+
|
|
8
22
|
module ClientAPI
|
|
9
23
|
# see Sapling::API::Client
|
|
10
24
|
def active?(feature, options={})
|
|
11
25
|
options = Util.normalized_options options
|
|
12
|
-
v =Model.count(:conditions =>
|
|
13
|
-
"feature = ? AND ((user_id IS NOT NULL AND user_id = ?) OR (percentage IS NOT NULL AND ? < percentage)) ",
|
|
14
|
-
feature,
|
|
15
|
-
(u=options[:user]) && u.id,
|
|
16
|
-
((c=options[:context_id]) && c%100) || 100
|
|
17
|
-
])
|
|
26
|
+
v = Model.count(:conditions => query_conditions(feature,options))
|
|
18
27
|
v > 0
|
|
19
28
|
end
|
|
29
|
+
|
|
30
|
+
def features
|
|
31
|
+
features = Model.find :all, :select => "feature", :group => "feature", :order => "feature"
|
|
32
|
+
features.map {|record| record.feature.to_sym}
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# returns a list of features enabled for a user
|
|
36
|
+
# see Sapling::API::Client
|
|
37
|
+
def active_features(options={})
|
|
38
|
+
options = Util.normalized_options options
|
|
39
|
+
features = Model.find :all, :conditions => query_conditions(nil,options)
|
|
40
|
+
features.map {|record| record.feature.to_sym}.uniq
|
|
41
|
+
end
|
|
20
42
|
end
|
|
21
43
|
include ClientAPI
|
|
22
44
|
|
|
@@ -25,25 +47,25 @@ module Sapling
|
|
|
25
47
|
def activate_user(feature, user)
|
|
26
48
|
Model.transaction do
|
|
27
49
|
deactivate_user(feature, user)
|
|
28
|
-
Model.create(:feature => feature, :user_id => user.id)
|
|
50
|
+
Model.create(:feature => feature.to_s, :user_id => user.id)
|
|
29
51
|
end
|
|
30
52
|
end
|
|
31
53
|
|
|
32
54
|
def deactivate_user(feature, user)
|
|
33
|
-
Model.delete_all ["feature = ? AND percentage IS NULL and user_id = ?",feature,user.id]
|
|
55
|
+
Model.delete_all ["feature = ? AND percentage IS NULL and user_id = ?",feature.to_s,user.id]
|
|
34
56
|
end
|
|
35
57
|
|
|
36
58
|
def activate_percentage(feature, percentage)
|
|
37
59
|
raise "invalid percentage #{percentage.inspect}" unless percentage.kind_of?(Integer) && percentage>=0 && percentage<=100
|
|
38
60
|
Model.transaction do
|
|
39
61
|
deactivate_percentage(feature)
|
|
40
|
-
Model.create(:feature => feature, :percentage => percentage)
|
|
62
|
+
Model.create(:feature => feature.to_s, :percentage => percentage)
|
|
41
63
|
end
|
|
42
64
|
end
|
|
43
65
|
|
|
44
66
|
def deactivate_percentage(feature)
|
|
45
67
|
Model.delete_all ["feature = ? AND percentage IS NOT NULL AND user_id IS NULL",
|
|
46
|
-
feature
|
|
68
|
+
feature.to_s
|
|
47
69
|
]
|
|
48
70
|
end
|
|
49
71
|
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
require "set"
|
|
2
|
+
|
|
3
|
+
module Sapling
|
|
4
|
+
class CssGenerator
|
|
5
|
+
attr_accessor :sapling
|
|
6
|
+
|
|
7
|
+
def initialize(sapling)
|
|
8
|
+
@sapling=sapling
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def prefix
|
|
12
|
+
"sapling_css"
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def css_class(feature, on)
|
|
16
|
+
"#{prefix}_#{feature.to_s}_#{on ? 'on' : 'off'}"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# see Sapling::API::Client for options
|
|
20
|
+
def to_s(options={})
|
|
21
|
+
features = Set.new @sapling.features
|
|
22
|
+
active_features = Set.new @sapling.active_features options
|
|
23
|
+
inactive_features = features - active_features
|
|
24
|
+
|
|
25
|
+
[
|
|
26
|
+
active_features.collect {|f|".#{css_class(f, false)} { display:none !important; }"},
|
|
27
|
+
inactive_features.collect {|f|".#{css_class(f, true)} { display:none !important; }"},
|
|
28
|
+
].flatten.join("\n")
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
data/lib/sapling/memory.rb
CHANGED
|
@@ -11,12 +11,12 @@ module Sapling
|
|
|
11
11
|
|
|
12
12
|
# see Sapling::API::Client
|
|
13
13
|
def active?(options={})
|
|
14
|
-
options = Util
|
|
14
|
+
options = Util.normalized_options(options)
|
|
15
15
|
individually_active?(options[:user]) || percentage_active?(options)
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
def percentage_active?(options={})
|
|
19
|
-
(Util.
|
|
19
|
+
(Util.modded_context_id(options)) < percentage
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
def individually_active?(user)
|
|
@@ -40,8 +40,6 @@ module Sapling
|
|
|
40
40
|
end
|
|
41
41
|
end
|
|
42
42
|
|
|
43
|
-
attr_accessor :features
|
|
44
|
-
|
|
45
43
|
def initialize
|
|
46
44
|
@features={}
|
|
47
45
|
end
|
|
@@ -49,14 +47,23 @@ module Sapling
|
|
|
49
47
|
module ClientAPI
|
|
50
48
|
# see Sapling::API::Client
|
|
51
49
|
def active?(feature, options={})
|
|
52
|
-
options = Util
|
|
50
|
+
options = Util.normalized_options(options)
|
|
53
51
|
(f = @features[feature]) && f.active?(options)
|
|
54
52
|
end
|
|
53
|
+
|
|
54
|
+
def features
|
|
55
|
+
@features.keys.sort_by {|k| k.to_s}
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# see Sapling::API::Client
|
|
59
|
+
def active_features(options={})
|
|
60
|
+
features.select {|feature| active?(feature,options)}
|
|
61
|
+
end
|
|
55
62
|
end
|
|
56
63
|
|
|
57
64
|
module AdminAPI
|
|
58
65
|
def activate_feature(feature)
|
|
59
|
-
features[feature]||=Feature.new
|
|
66
|
+
@features[feature]||=Feature.new
|
|
60
67
|
end
|
|
61
68
|
|
|
62
69
|
def activate_user(feature, user)
|
|
@@ -64,7 +71,7 @@ module Sapling
|
|
|
64
71
|
end
|
|
65
72
|
|
|
66
73
|
def deactivate_user(feature, user)
|
|
67
|
-
(f
|
|
74
|
+
(f=@features[feature]) && f.deactivate_user(user)
|
|
68
75
|
end
|
|
69
76
|
|
|
70
77
|
def activate_percentage(feature, percentage)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require 'sapling/rails/action_controller'
|
|
2
|
+
require 'sapling/rails/view_helpers'
|
|
3
|
+
|
|
4
|
+
ActiveSupport::Dependencies.autoload_paths << File.expand_path(File.join(File.dirname(__FILE__), "rails", "controllers"))
|
|
5
|
+
|
|
6
|
+
ActionController::Routing::Routes.draw do |map|
|
|
7
|
+
map.sapling_stylesheet 'sapling/stylesheet.css', :controller => 'sapling', :action => 'stylesheet'
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
if defined?(Rails)
|
|
11
|
+
if Rails.version =~ /^3\./
|
|
12
|
+
# Haven't tested this
|
|
13
|
+
require 'sapling/rails/railtie'
|
|
14
|
+
else
|
|
15
|
+
ActionView::Base.send :include, Sapling::ViewHelpers
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
require 'action_controller'
|
|
2
|
+
|
|
3
|
+
module Sapling::ActionControllerExt
|
|
4
|
+
def feature_active?(feature, options={})
|
|
5
|
+
options[:user] ||= current_user
|
|
6
|
+
sapling.active?(feature, options)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def sapling
|
|
11
|
+
@@sapling ||= Sapling::ActiveRecord.new
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def sapling_css_generator
|
|
15
|
+
@@sapling_css_generator ||= Sapling::CssGenerator.new(sapling)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
class ActionController::Base
|
|
21
|
+
include Sapling::ActionControllerExt
|
|
22
|
+
helper_method :feature_active?, :sapling, :sapling_css_generator
|
|
23
|
+
end
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
class SaplingController < ApplicationController
|
|
2
|
+
def stylesheet
|
|
3
|
+
styles = sapling_css_generator.to_s(:user => current_user, :context_id => (request.session_options[:id] if request.session))
|
|
4
|
+
# styles = "boo"
|
|
5
|
+
render :text => styles, :content_type => 'text/css'
|
|
6
|
+
end
|
|
7
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module Sapling
|
|
2
|
+
module ViewHelpers
|
|
3
|
+
|
|
4
|
+
# include ActionView::Helpers::CaptureHelper
|
|
5
|
+
def feature_on(feature, &block)
|
|
6
|
+
feature_block(sapling_css_generator.css_class(feature, "style=\"display:none;\"", true), &block)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def feature_off(feature, &block)
|
|
10
|
+
feature_block(sapling_css_generator.css_class(feature, nil, false), &block)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
private
|
|
14
|
+
def feature_block(css_class, params, &block)
|
|
15
|
+
concat "<span class=\"#{css_class}\" #{params}>"
|
|
16
|
+
block.call
|
|
17
|
+
concat "</span>"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
data/lib/sapling/util.rb
CHANGED
|
@@ -1,21 +1,19 @@
|
|
|
1
1
|
module Sapling
|
|
2
2
|
class Util
|
|
3
|
+
CONTEXT_ID_ONLY_ENABLED_IF_100_PERCENT_ENABLED = 99
|
|
4
|
+
|
|
3
5
|
class << self
|
|
4
6
|
def context_id(options)
|
|
5
|
-
options[:context_id] || options[:user].id
|
|
7
|
+
options[:context_id] || ((u=options[:user]) && u.id)
|
|
8
|
+
end
|
|
9
|
+
def modded_context_id(options)
|
|
10
|
+
((cid=context_id(options)) && (cid%100)) || CONTEXT_ID_ONLY_ENABLED_IF_100_PERCENT_ENABLED
|
|
6
11
|
end
|
|
7
12
|
|
|
8
13
|
def normalized_options(options)
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
options
|
|
13
|
-
when Integer then
|
|
14
|
-
{:context_id => options}
|
|
15
|
-
else
|
|
16
|
-
user=options
|
|
17
|
-
{:user => user, :context_id => user.id}
|
|
18
|
-
end
|
|
14
|
+
options[:user_id] ||= options[:user].id if options[:user]
|
|
15
|
+
options[:context_id] ||= options[:user_id]
|
|
16
|
+
options
|
|
19
17
|
end
|
|
20
18
|
end
|
|
21
19
|
end
|
data/lib/sapling/version.rb
CHANGED
data/rails/init.rb
ADDED
data/sapling.gemspec
CHANGED
|
@@ -8,8 +8,8 @@ Gem::Specification.new do |s|
|
|
|
8
8
|
s.authors = ["Shane Brinkman-Davis", "Jason Strutz"]
|
|
9
9
|
s.email = ["shanebdavis@imikimi.com", "jason@cumuluscode.com"]
|
|
10
10
|
s.homepage = ""
|
|
11
|
-
s.summary = %q{
|
|
12
|
-
s.description = %q{}
|
|
11
|
+
s.summary = %q{Incrementally roll out your features. Uses ActiveRecord to store configuration and supports client-side roll-out of cached pages.}
|
|
12
|
+
s.description = %q{Sapling lets you seed your new features to just a few users at a time. You can change which and how many users are seeded for a feature dynamically by updating the database via the Sapling API. Core features are the ability to seed a feature for specific users and/or a percentage of users.}
|
|
13
13
|
|
|
14
14
|
s.rubyforge_project = "sapling"
|
|
15
15
|
|
|
@@ -19,8 +19,9 @@ Gem::Specification.new do |s|
|
|
|
19
19
|
s.require_paths = ["lib"]
|
|
20
20
|
|
|
21
21
|
# specify any dependencies here; for example:
|
|
22
|
+
s.add_runtime_dependency "activerecord", ">2.3"
|
|
22
23
|
s.add_development_dependency "rspec", "~>2.7.0"
|
|
24
|
+
s.add_development_dependency "rails", "2.3.12"
|
|
23
25
|
s.add_development_dependency "mocha"
|
|
24
|
-
s.add_development_dependency "activerecord", "~>3.1.1"
|
|
25
26
|
s.add_development_dependency "sqlite3", "~>1.3.4"
|
|
26
27
|
end
|
data/spec/active_record_spec.rb
CHANGED
|
@@ -12,31 +12,5 @@ describe "Sapling::ActiveRecord" do
|
|
|
12
12
|
ActiveRecord::Base.connection.execute sql
|
|
13
13
|
@sapling = Sapling::ActiveRecord.new
|
|
14
14
|
end
|
|
15
|
-
|
|
16
15
|
end
|
|
17
|
-
#
|
|
18
|
-
# it "should init" do
|
|
19
|
-
# Sapling::Memory.new
|
|
20
|
-
# end
|
|
21
|
-
#
|
|
22
|
-
# it "should support activating users" do
|
|
23
|
-
# mem = Sapling::Memory.new
|
|
24
|
-
# user = UserMock.new
|
|
25
|
-
#
|
|
26
|
-
# mem.active?(:my_feature, user).should be_false
|
|
27
|
-
#
|
|
28
|
-
# mem.activate_user(:my_feature, user)
|
|
29
|
-
# mem.active?(:my_feature, user).should be_true
|
|
30
|
-
# end
|
|
31
|
-
#
|
|
32
|
-
# it "should support deactivating users" do
|
|
33
|
-
# mem = Sapling::Memory.new
|
|
34
|
-
# user = UserMock.new
|
|
35
|
-
#
|
|
36
|
-
# mem.activate_user(:my_feature, user)
|
|
37
|
-
# mem.active?(:my_feature, user).should be_true
|
|
38
|
-
#
|
|
39
|
-
# mem.deactivate_user(:my_feature, user)
|
|
40
|
-
# mem.active?(:my_feature, user).should be_false
|
|
41
|
-
# end
|
|
42
16
|
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
|
2
|
+
|
|
3
|
+
describe "Sapling::CssGenerator" do
|
|
4
|
+
|
|
5
|
+
before do
|
|
6
|
+
ActiveRecord::Base.establish_connection(
|
|
7
|
+
:adapter => 'sqlite3',
|
|
8
|
+
:database => ':memory:'
|
|
9
|
+
)
|
|
10
|
+
sql = File.read(File.expand_path(File.dirname(__FILE__) + '/../db/create.sql'))
|
|
11
|
+
ActiveRecord::Base.connection.execute sql
|
|
12
|
+
@sapling = Sapling::ActiveRecord.new
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
describe "creating basic css" do
|
|
16
|
+
before do
|
|
17
|
+
@sapling.activate_user(:chat, stub(:id => 1))
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it "outputs css" do
|
|
21
|
+
Sapling::CssGenerator.new(@sapling).to_s(:user => stub(:id => 1)).should == ".sapling_css_chat_off { display:none !important; }"
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
describe "creating more complex css" do
|
|
26
|
+
before do
|
|
27
|
+
@sapling.activate_percentage(:bicycle, 10)
|
|
28
|
+
@sapling.activate_user(:chat, stub(:id => 115))
|
|
29
|
+
@sapling.activate_user(:pwn, stub(:id => 102))
|
|
30
|
+
@sapling.activate_user(:juggle, stub(:id => 115))
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "test user bicycle & pwn user" do
|
|
34
|
+
output = Sapling::CssGenerator.new(@sapling).to_s(:user => stub(:id => 102))
|
|
35
|
+
%w{ bicycle_off chat_on juggle_on pwn_off }.each do |key|
|
|
36
|
+
output.should =~ /#{key}[^}]+?display:none/
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it "test chat & juggle user" do
|
|
41
|
+
output = Sapling::CssGenerator.new(@sapling).to_s(:user => stub(:id => 115))
|
|
42
|
+
%w{ bicycle_on chat_off juggle_off pwn_on }.each do |key|
|
|
43
|
+
output.should =~ /#{key}[^}]+?display:none/
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
data/spec/memory_feature_spec.rb
CHANGED
|
@@ -5,9 +5,9 @@ describe "Sapling::Memory::Feature" do
|
|
|
5
5
|
f=Sapling::Memory::Feature.new
|
|
6
6
|
u=UserMock.new
|
|
7
7
|
|
|
8
|
-
f.active?(u).should be_false
|
|
8
|
+
f.active?(:user=>u).should be_false
|
|
9
9
|
f.activate_user(u)
|
|
10
10
|
|
|
11
|
-
f.active?(u).should be_true
|
|
11
|
+
f.active?(:user=>u).should be_true
|
|
12
12
|
end
|
|
13
13
|
end
|
data/spec/memory_spec.rb
CHANGED
|
@@ -5,31 +5,5 @@ describe "Sapling::Memory" do
|
|
|
5
5
|
before do
|
|
6
6
|
@sapling = Sapling::Memory.new
|
|
7
7
|
end
|
|
8
|
-
|
|
9
8
|
end
|
|
10
|
-
#
|
|
11
|
-
# it "should init" do
|
|
12
|
-
# Sapling::Memory.new
|
|
13
|
-
# end
|
|
14
|
-
#
|
|
15
|
-
# it "should support activating users" do
|
|
16
|
-
# mem = Sapling::Memory.new
|
|
17
|
-
# user = UserMock.new
|
|
18
|
-
#
|
|
19
|
-
# mem.active?(:my_feature, user).should be_false
|
|
20
|
-
#
|
|
21
|
-
# mem.activate_user(:my_feature, user)
|
|
22
|
-
# mem.active?(:my_feature, user).should be_true
|
|
23
|
-
# end
|
|
24
|
-
#
|
|
25
|
-
# it "should support deactivating users" do
|
|
26
|
-
# mem = Sapling::Memory.new
|
|
27
|
-
# user = UserMock.new
|
|
28
|
-
#
|
|
29
|
-
# mem.activate_user(:my_feature, user)
|
|
30
|
-
# mem.active?(:my_feature, user).should be_true
|
|
31
|
-
#
|
|
32
|
-
# mem.deactivate_user(:my_feature, user)
|
|
33
|
-
# mem.active?(:my_feature, user).should be_false
|
|
34
|
-
# end
|
|
35
9
|
end
|