mist 0.6.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 +18 -0
- data/.rspec +1 -0
- data/.rvmrc +1 -0
- data/.travis.yml +13 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +192 -0
- data/README.md +108 -0
- data/Rakefile +9 -0
- data/app/assets/images/mist/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
- data/app/assets/images/mist/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
- data/app/assets/images/mist/ui-bg_flat_10_000000_40x100.png +0 -0
- data/app/assets/images/mist/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
- data/app/assets/images/mist/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
- data/app/assets/images/mist/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/app/assets/images/mist/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
- data/app/assets/images/mist/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
- data/app/assets/images/mist/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
- data/app/assets/images/mist/ui-icons_222222_256x240.png +0 -0
- data/app/assets/images/mist/ui-icons_228ef1_256x240.png +0 -0
- data/app/assets/images/mist/ui-icons_ef8c08_256x240.png +0 -0
- data/app/assets/images/mist/ui-icons_ffd27a_256x240.png +0 -0
- data/app/assets/images/mist/ui-icons_ffffff_256x240.png +0 -0
- data/app/assets/javascripts/mist/jquery-ui-1.8.17.custom.min.js +356 -0
- data/app/assets/javascripts/mist/posts.js.coffee +3 -0
- data/app/assets/javascripts/mist_core.js +3 -0
- data/app/assets/stylesheets/mist/posts.css.sass +97 -0
- data/app/assets/stylesheets/mist/scaffolds.css.scss +56 -0
- data/app/assets/stylesheets/mist/ui-lightness/jquery-ui-1.8.17.custom.css +565 -0
- data/app/assets/stylesheets/mist_core.css +4 -0
- data/app/controllers/application_controller.rb +3 -0
- data/app/controllers/mist/posts_controller.rb +130 -0
- data/app/helpers/mist/posts_helper.rb +61 -0
- data/app/mailers/.gitkeep +0 -0
- data/app/models/.gitkeep +0 -0
- data/app/models/mist/post.rb +240 -0
- data/app/models/mist/post_sweeper.rb +63 -0
- data/app/views/layouts/mist/posts.html.erb +66 -0
- data/app/views/mist/posts/_form.html.erb +55 -0
- data/app/views/mist/posts/_post.html.erb +19 -0
- data/app/views/mist/posts/_sidebar_title.html.erb +5 -0
- data/app/views/mist/posts/edit.html.erb +16 -0
- data/app/views/mist/posts/feed.atom.builder +17 -0
- data/app/views/mist/posts/index.html.erb +31 -0
- data/app/views/mist/posts/new.html.erb +15 -0
- data/app/views/mist/posts/show.html.erb +3 -0
- data/config/cucumber.yml +8 -0
- data/config/environment.rb +1 -0
- data/config/routes.rb +7 -0
- data/features/atom_feed.feature +20 -0
- data/features/authorize_create_post.feature +14 -0
- data/features/authorize_destroy_post.feature +27 -0
- data/features/authorize_update_post.feature +28 -0
- data/features/authorize_view_unpublished.feature +22 -0
- data/features/create_post.feature +13 -0
- data/features/destroy_post.feature +13 -0
- data/features/format_with_markdown.feature +13 -0
- data/features/popular_posts.feature +35 -0
- data/features/recent_posts.feature +28 -0
- data/features/similar_posts.feature +43 -0
- data/features/step_definitions/authorization_steps.rb +17 -0
- data/features/step_definitions/filesystem_steps.rb +13 -0
- data/features/step_definitions/page_steps.rb +43 -0
- data/features/step_definitions/post_steps.rb +58 -0
- data/features/step_definitions/sidebar_steps.rb +21 -0
- data/features/support/env.rb +58 -0
- data/features/support/setup.rb +15 -0
- data/features/update_post.feature +19 -0
- data/gemfiles/common +20 -0
- data/gemfiles/rails-3.1.3 +4 -0
- data/gemfiles/rails-3.1.3.lock +195 -0
- data/gemfiles/rails-3.2.0 +4 -0
- data/lib/generators/mist/USAGE +13 -0
- data/lib/generators/mist/setup_generator.rb +21 -0
- data/lib/generators/mist/templates/initializer.rb +17 -0
- data/lib/generators/mist/templates/mist.css.scss +2 -0
- data/lib/generators/mist/templates/mist.js.coffee +1 -0
- data/lib/generators/mist/views_generator.rb +11 -0
- data/lib/mist.rb +26 -0
- data/lib/mist/code_example_parser.rb +86 -0
- data/lib/mist/configuration.rb +68 -0
- data/lib/mist/configuration/author.rb +8 -0
- data/lib/mist/engine.rb +12 -0
- data/lib/mist/git_file_system_history.rb +66 -0
- data/lib/mist/git_model.rb +154 -0
- data/lib/mist/git_model/attributes.rb +21 -0
- data/lib/mist/git_model/class_methods.rb +141 -0
- data/lib/mist/permalink.rb +5 -0
- data/lib/mist/repository.rb +15 -0
- data/lib/mist/version.rb +8 -0
- data/mist.gemspec +33 -0
- data/spec/controllers/posts_controller_spec.rb +263 -0
- data/spec/dummy_rails_app/app/assets/javascripts/mist.js.coffee +1 -0
- data/spec/dummy_rails_app/app/assets/stylesheets/mist.css.scss +2 -0
- data/spec/dummy_rails_app/app/views/layouts/mist/posts.html.erb +60 -0
- data/spec/dummy_rails_app/config.ru +4 -0
- data/spec/dummy_rails_app/config/application.rb +48 -0
- data/spec/dummy_rails_app/config/boot.rb +7 -0
- data/spec/dummy_rails_app/config/database.yml +28 -0
- data/spec/dummy_rails_app/config/environment.rb +5 -0
- data/spec/dummy_rails_app/config/environments/development.rb +32 -0
- data/spec/dummy_rails_app/config/environments/production.rb +60 -0
- data/spec/dummy_rails_app/config/environments/test.rb +42 -0
- data/spec/dummy_rails_app/config/initializers/active_gist_credentials.rb +8 -0
- data/spec/dummy_rails_app/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy_rails_app/config/initializers/inflections.rb +10 -0
- data/spec/dummy_rails_app/config/initializers/mime_types.rb +5 -0
- data/spec/dummy_rails_app/config/initializers/mist.rb +17 -0
- data/spec/dummy_rails_app/config/initializers/secret_token.rb +7 -0
- data/spec/dummy_rails_app/config/initializers/session_store.rb +8 -0
- data/spec/dummy_rails_app/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy_rails_app/config/locales/en.yml +5 -0
- data/spec/dummy_rails_app/config/routes.rb +3 -0
- data/spec/dummy_rails_app/db/schema.rb +22 -0
- data/spec/dummy_rails_app/db/seeds.rb +7 -0
- data/spec/dummy_rails_app/doc/README_FOR_APP +2 -0
- data/spec/dummy_rails_app/lib/assets/.gitkeep +0 -0
- data/spec/dummy_rails_app/lib/tasks/.gitkeep +0 -0
- data/spec/dummy_rails_app/lib/tasks/cucumber.rake +65 -0
- data/spec/dummy_rails_app/public/404.html +26 -0
- data/spec/dummy_rails_app/public/422.html +26 -0
- data/spec/dummy_rails_app/public/500.html +26 -0
- data/spec/dummy_rails_app/public/favicon.ico +0 -0
- data/spec/dummy_rails_app/public/robots.txt +5 -0
- data/spec/dummy_rails_app/script/cucumber +10 -0
- data/spec/dummy_rails_app/script/rails +6 -0
- data/spec/dummy_rails_app/vendor/assets/stylesheets/.gitkeep +0 -0
- data/spec/dummy_rails_app/vendor/plugins/.gitkeep +0 -0
- data/spec/factories/posts.rb +8 -0
- data/spec/fixtures/gist_404 +6 -0
- data/spec/fixtures/gist_with_1_code_example +66 -0
- data/spec/helpers/posts_helper_spec.rb +64 -0
- data/spec/lib/mist/code_example_parser_spec.rb +135 -0
- data/spec/lib/mist/configuration_spec.rb +88 -0
- data/spec/lib/mist/permalink_spec.rb +17 -0
- data/spec/lib/mist/repository_spec.rb +20 -0
- data/spec/models/mist/git_model_spec.rb +260 -0
- data/spec/models/mist/post_spec.rb +575 -0
- data/spec/requests/posts_caching_spec.rb +152 -0
- data/spec/spec_helper.rb +20 -0
- data/spec/support/cache_helpers.rb +71 -0
- data/spec/support/config.rb +42 -0
- data/spec/support/fakeweb.rb +3 -0
- data/spec/views/mist/posts/edit.html.erb_spec.rb +11 -0
- data/spec/views/mist/posts/index.html.erb_spec.rb +27 -0
- data/spec/views/mist/posts/new.html.erb_spec.rb +15 -0
- data/spec/views/mist/posts/show.html.erb_spec.rb +11 -0
- metadata +371 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Mist::Configuration do
|
|
4
|
+
subject { Class.new { include Mist::Configuration }.new }
|
|
5
|
+
|
|
6
|
+
it "should have a default repo location" do
|
|
7
|
+
subject.repository_location.should_not be_blank
|
|
8
|
+
subject.repository_location.should == subject.default_repository_location
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it "should allow repo location to be set" do
|
|
12
|
+
subject.repository_location = "123"
|
|
13
|
+
subject.repository_location.should == '123'
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
describe "authorization" do
|
|
17
|
+
it "should accept multiple arguments" do
|
|
18
|
+
Mist.authorize(:one, :two) { true }
|
|
19
|
+
Mist.should be_authorized(:one)
|
|
20
|
+
Mist.should be_authorized(:two)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "should work default to :all given no arguments" do
|
|
24
|
+
Mist.authorize { true }
|
|
25
|
+
Mist.should be_authorized(:create_post)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it "should require a block to set up" do
|
|
29
|
+
proc { Mist.authorize(:test) }.should raise_error(ArgumentError)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
describe "with authorization for a single action" do
|
|
33
|
+
before { Mist.authorize(:test) { |*c| @received = c; true } }
|
|
34
|
+
|
|
35
|
+
it "should return the block result" do
|
|
36
|
+
Mist.should be_authorized(:test)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "should pass extra arguments to the block" do
|
|
40
|
+
Mist.authorized?(:test, 1, 2, 3)
|
|
41
|
+
@received.should == [1, 2, 3]
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it "should return false for other actions" do
|
|
45
|
+
Mist.should_not be_authorized(:other)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it "should reset" do
|
|
49
|
+
Mist.reset_authorizations!
|
|
50
|
+
Mist.should_not be_authorized(:test)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
describe "with authorization for all actions" do
|
|
55
|
+
before { Mist.authorize(:all) { true } }
|
|
56
|
+
|
|
57
|
+
it "should return block result for any action" do
|
|
58
|
+
Mist.should be_authorized(:test)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
describe "by default" do
|
|
63
|
+
it "should deny authorization for all actions" do
|
|
64
|
+
Mist.should_not be_authorized(:test)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
describe "overriding all actions with a given action" do
|
|
69
|
+
before { Mist.authorize(:all) { true }; Mist.authorize(:test) { false } }
|
|
70
|
+
|
|
71
|
+
it "should return overridden result for the overridden action" do
|
|
72
|
+
Mist.should_not be_authorized(:test)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
it "should not return overridden result for other actions" do
|
|
76
|
+
Mist.should be_authorized(:other)
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
describe "overriding the same action" do
|
|
81
|
+
before { Mist.authorize(:test) { false }; Mist.authorize(:test) { true } }
|
|
82
|
+
|
|
83
|
+
it "should use the last block given" do
|
|
84
|
+
Mist.should be_authorized(:test)
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Mist::Permalink do
|
|
4
|
+
include Mist::Permalink
|
|
5
|
+
|
|
6
|
+
it "should not include periods" do # they screw with rails' formats
|
|
7
|
+
permalink("Stuck in Rails 2? Use Bundler. For everything. Right now.").should_not match(/\./)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it "should not create double dashes" do # they're ugly
|
|
11
|
+
permalink("Stuck in Rails 2? Use Bundler. For everything. Right now.").should_not match(/--/)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it "should not end with dashes" do # ditto
|
|
15
|
+
permalink("Stuck in Rails 2? Use Bundler. For everything. Right now.").should_not match(/-$/)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Mist do
|
|
4
|
+
it "should generate the repo automatically" do
|
|
5
|
+
Mist.repository
|
|
6
|
+
File.should be_directory(Mist.repository_location.join('.git'))
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
describe "with an existing repo" do
|
|
10
|
+
before do
|
|
11
|
+
Git.init(Mist.repository_location.to_s)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it "should not generate the repo" do
|
|
15
|
+
Git.should_not_receive(:init)
|
|
16
|
+
|
|
17
|
+
Mist.repository
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'mist/git_model'
|
|
3
|
+
|
|
4
|
+
describe Mist::GitModel do
|
|
5
|
+
let(:model_class) { Class.new(Mist::GitModel) { def self.name; "TestModel"; end } }
|
|
6
|
+
subject { model_class.new }
|
|
7
|
+
|
|
8
|
+
describe "when no records ever existed" do
|
|
9
|
+
it "last record should be nil" do
|
|
10
|
+
model_class.last.should be_nil
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "last 5 records should be empty" do
|
|
14
|
+
model_class.last(5).should be_empty
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
describe "when 1 record exists" do
|
|
19
|
+
before { model_class.create! }
|
|
20
|
+
it "last record should be the record" do
|
|
21
|
+
model_class.last.should be_kind_of(model_class)
|
|
22
|
+
end
|
|
23
|
+
it "last 5 records should be 1-element" do
|
|
24
|
+
model_class.last(5).should have(1).record
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
describe "when 2 records exist" do
|
|
29
|
+
before { model_class.create!; model_class.create! }
|
|
30
|
+
it "last record should be returned" do
|
|
31
|
+
model_class.last.should be_kind_of(model_class)
|
|
32
|
+
end
|
|
33
|
+
it 'last 5 records should contain 2' do
|
|
34
|
+
model_class.last(5).should have(2).records
|
|
35
|
+
end
|
|
36
|
+
it 'should return them in order, most recent first' do
|
|
37
|
+
model_class.last(5).collect { |i| i.id }.should == ['2', '1']
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
describe "when 10 records exist" do
|
|
42
|
+
before { 10.times { model_class.create! } }
|
|
43
|
+
it "last 5 records should not exceed 5" do
|
|
44
|
+
model_class.last(5).should have(5).records
|
|
45
|
+
end
|
|
46
|
+
it 'should return them in order, most recent first' do
|
|
47
|
+
model_class.last(5).collect { |i| i.id }.should == ['10', '9', '8', '7', '6']
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it "should underscore and pluralize #table_name" do
|
|
52
|
+
subject.table_name.should == 'test_models'
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it "should not be changed" do
|
|
56
|
+
# applying defaults should not be considered a change to a new record
|
|
57
|
+
subject.should_not be_changed
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
describe "validation" do
|
|
61
|
+
it "should be wrapped in callbacks" do
|
|
62
|
+
before = after = false
|
|
63
|
+
model_class.before_validation { before = true }
|
|
64
|
+
model_class.after_validation { after = true }
|
|
65
|
+
|
|
66
|
+
model_class.new.valid?
|
|
67
|
+
before.should be_true
|
|
68
|
+
after.should be_true
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it "should not require id" do
|
|
72
|
+
subject.valid?
|
|
73
|
+
subject.errors[:id].should_not include("can't be blank")
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
describe "with an id" do
|
|
77
|
+
before { subject.id = 1 }
|
|
78
|
+
|
|
79
|
+
it "should enforce uniqueness of id" do
|
|
80
|
+
subject.save!
|
|
81
|
+
|
|
82
|
+
other = model_class.new(:id => 1)
|
|
83
|
+
other.valid?
|
|
84
|
+
other.errors[:id].should include("has already been taken")
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
describe "creation" do
|
|
90
|
+
subject { model_class.create! }
|
|
91
|
+
|
|
92
|
+
it "should return the model" do
|
|
93
|
+
subject.should be_kind_of(model_class)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
it "should not be a new record" do
|
|
97
|
+
subject.should_not be_new_record
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
it "should have an id" do
|
|
101
|
+
subject.id.should_not be_blank
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
it "should find it by its id" do
|
|
105
|
+
model_class.find(subject.id).should == subject
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
describe "new default record" do
|
|
110
|
+
it { should_not be_persisted }
|
|
111
|
+
it { should be_new_record }
|
|
112
|
+
it { should_not be_changed }
|
|
113
|
+
|
|
114
|
+
describe "after saving" do
|
|
115
|
+
before { subject.save! }
|
|
116
|
+
|
|
117
|
+
it { should be_persisted }
|
|
118
|
+
it { should_not be_new_record }
|
|
119
|
+
it { should_not be_changed }
|
|
120
|
+
|
|
121
|
+
it "should increase count" do
|
|
122
|
+
model_class.count.should == 1
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
it "should have created a file record" do
|
|
126
|
+
File.should be_file(subject.path)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
it "should have created a commit" do
|
|
130
|
+
Mist.log.size.should == 1
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
it "should load the content in a separate query" do
|
|
134
|
+
model_class.find(subject.id).id.should == subject.id
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
describe "an existing record" do
|
|
140
|
+
subject { model_class.create! }
|
|
141
|
+
|
|
142
|
+
describe "altered on file system" do
|
|
143
|
+
it "should load id from filename, not from file contents" do
|
|
144
|
+
# create a tainted record directly on the filesystem
|
|
145
|
+
yaml = YAML.load(File.read(subject.path))
|
|
146
|
+
yaml['id'] = '2'
|
|
147
|
+
new_path = File.expand_path('3', File.dirname(subject.path))
|
|
148
|
+
File.open(new_path, "w") { |f| f.print yaml.to_yaml }
|
|
149
|
+
|
|
150
|
+
# now load it
|
|
151
|
+
model_class.find('3').id.should == '3'
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
describe "files renamed on file system but not committed to git" do
|
|
155
|
+
before do
|
|
156
|
+
FileUtils.mv subject.path, File.expand_path('2', File.dirname(subject.path))
|
|
157
|
+
model
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
let :model do
|
|
161
|
+
model = model_class.find('2')
|
|
162
|
+
model.save!
|
|
163
|
+
model
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
it "should use the renamed file's id" do
|
|
167
|
+
model.id.should == '2'
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
it "should commit the new file to git" do
|
|
171
|
+
File.should exist(File.expand_path('2', File.dirname(model.path)))
|
|
172
|
+
Mist.repository.lib.diff_files.should be_empty
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
it "should remove the missing file from git" do
|
|
176
|
+
File.should_not exist(subject.path)
|
|
177
|
+
Mist.repository.lib.diff_files.should be_empty
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
describe "destroying" do
|
|
183
|
+
before { subject.destroy }
|
|
184
|
+
|
|
185
|
+
it "should not be found" do
|
|
186
|
+
model_class.find(subject.id).should be_nil
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
it "should produce a commit" do
|
|
190
|
+
Mist.log.size.should == 2
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
it "should reduce count" do
|
|
194
|
+
model_class.count.should == 0
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
describe "with an attribute" do
|
|
199
|
+
before { model_class.attribute(:content); subject.save! }
|
|
200
|
+
|
|
201
|
+
describe "changing an attribute" do
|
|
202
|
+
before { subject.content = "changed"; subject.save! }
|
|
203
|
+
|
|
204
|
+
it "should create a commit" do
|
|
205
|
+
Mist.log.size.should == 2
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
it "should load the new content in a separate query" do
|
|
209
|
+
model_class.find(subject.id).content.should == "changed"
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
describe "changing its id and its attribute simultaneously" do
|
|
214
|
+
before do
|
|
215
|
+
@old_path = subject.path
|
|
216
|
+
subject.id = 2
|
|
217
|
+
subject.content = "changed"
|
|
218
|
+
subject.save!
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
it "should create a commit" do
|
|
222
|
+
Mist.log.size.should == 2
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
it "should have changed the content path" do
|
|
226
|
+
@old_path.should_not == subject.path
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
it "should have removed the old content path" do
|
|
230
|
+
File.should_not exist(@old_path)
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
it "should have created a new content path" do
|
|
234
|
+
File.should be_file(subject.path)
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
it "should load the new content in a separate query" do
|
|
238
|
+
model_class.find(subject.id).content.should == "changed"
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
describe "active model lint tests" do
|
|
246
|
+
include Test::Unit::Assertions
|
|
247
|
+
include ActiveModel::Lint::Tests
|
|
248
|
+
|
|
249
|
+
def model
|
|
250
|
+
subject
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
# to_s is to support ruby-1.9
|
|
254
|
+
ActiveModel::Lint::Tests.public_instance_methods.map{|m| m.to_s}.grep(/^test/).each do |m|
|
|
255
|
+
example m.gsub('_',' ') do
|
|
256
|
+
send m
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
end
|
|
260
|
+
end
|
|
@@ -0,0 +1,575 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Mist::Post do
|
|
4
|
+
it "preview" do
|
|
5
|
+
subject.content = "# This is a header and stuff\r\nHere's a paragraph, or it would be if
|
|
6
|
+
I had anything much to talk about, but it's really not right now because I'm busy.
|
|
7
|
+
Go away.\r\n\r\nHere's some sample code to keep you sated:\r\n\r\n file: test.rb\r\n
|
|
8
|
+
\ one = :one\r\n\r\n## and this is another header"
|
|
9
|
+
proc { subject.content_as_html_preview }.should_not raise_error
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it "should call observer" do
|
|
13
|
+
subject.title = subject.content = "title"
|
|
14
|
+
Mist::PostSweeper.instance.should_receive(:after_save)
|
|
15
|
+
subject.save
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
describe "Mist::Post#matching_tags" do
|
|
19
|
+
before do
|
|
20
|
+
Mist::Post.create!(attributes_for(:post).merge(:title => 'one', :tags => 'one'))
|
|
21
|
+
Mist::Post.create!(attributes_for(:post).merge(:title => 'two', :tags => 'two'))
|
|
22
|
+
Mist::Post.create!(attributes_for(:post).merge(:title => 'four', :tags => nil))
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "should return empty array if given nil" do
|
|
26
|
+
Mist::Post.matching_tags(nil).should be_empty
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "should return empty array if given empty string" do
|
|
30
|
+
Mist::Post.matching_tags([""]).should be_empty
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "should handle a single matching" do
|
|
34
|
+
Mist::Post.matching_tags(["one"]).should have(1).post
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it "should handle a single not matching" do
|
|
38
|
+
Mist::Post.matching_tags(["three"]).should be_empty
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it "should handle multiple matching" do
|
|
42
|
+
Mist::Post.matching_tags(['one', 'two']).should have(2).posts
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it "should handle multiple matching and not matching" do
|
|
46
|
+
Mist::Post.matching_tags(['one', 'three']).should have(1).post
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
describe "tags" do
|
|
51
|
+
it "should save them" do
|
|
52
|
+
id = Mist::Post.create!(attributes_for(:post).merge(:tags => ['one', 'two', 'three'])).id
|
|
53
|
+
Mist::Post.find(id).tags.should == ['one', 'two', 'three']
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it "should split them out of a string" do
|
|
57
|
+
p = Mist::Post.new
|
|
58
|
+
p.tags = 'one, two three,four'
|
|
59
|
+
p.tags.should == ['one', 'two three', 'four']
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
describe "recent posts" do
|
|
64
|
+
before do
|
|
65
|
+
@order = [ 1.day.ago, 2.days.ago, 3.days.ago, 4.days.ago, 5.days.ago ]
|
|
66
|
+
5.times { |i| Mist::Post.create!(:title => "title#{i}", :content => "content", :published_at => @order[i]) }
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
it "should order by published_at descending" do
|
|
70
|
+
Mist::Post.recently_published(5)[0].published_at.should == @order[0]
|
|
71
|
+
Mist::Post.recently_published(5)[1].published_at.should == @order[1]
|
|
72
|
+
Mist::Post.recently_published(5)[2].published_at.should == @order[2]
|
|
73
|
+
Mist::Post.recently_published(5)[3].published_at.should == @order[3]
|
|
74
|
+
Mist::Post.recently_published(5)[4].published_at.should == @order[4]
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
describe "popularity" do
|
|
79
|
+
before do
|
|
80
|
+
subject.title = "post title"
|
|
81
|
+
subject.content = "content"
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
it "should start at 0" do
|
|
85
|
+
subject.popularity.should == 0
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
it "should not affect equality" do
|
|
89
|
+
# a post is equal if its ID matches, nothing else matters.
|
|
90
|
+
subject.save!
|
|
91
|
+
other = Mist::Post.last
|
|
92
|
+
|
|
93
|
+
subject.popularity = 1
|
|
94
|
+
subject.save!
|
|
95
|
+
|
|
96
|
+
subject.should == other
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
it "should order by descending popularity" do
|
|
100
|
+
5.times { |i| Mist::Post.create!(:title => "title#{i}", :content => "content", :popularity => i) }
|
|
101
|
+
|
|
102
|
+
popular = Mist::Post.most_popular(5)
|
|
103
|
+
popular[0].popularity.should == 4
|
|
104
|
+
popular[1].popularity.should == 3
|
|
105
|
+
popular[2].popularity.should == 2
|
|
106
|
+
popular[3].popularity.should == 1
|
|
107
|
+
popular[4].popularity.should == 0
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
describe "after saving" do
|
|
111
|
+
before { subject.save! }
|
|
112
|
+
|
|
113
|
+
it "should be included in popular posts" do
|
|
114
|
+
Mist::Post.most_popular(5).should include(subject)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
describe "and then deleting" do
|
|
118
|
+
before { subject.destroy }
|
|
119
|
+
|
|
120
|
+
it "should omit subject from popular posts" do
|
|
121
|
+
Mist::Post.most_popular(5).should be_empty
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
describe "after popularity has changed" do
|
|
126
|
+
before { subject.popularity = 5; subject.save! }
|
|
127
|
+
|
|
128
|
+
it "should load the popularity" do
|
|
129
|
+
Mist::Post.find(subject.id).popularity.should == 5
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
it "should return the post as among the most popular" do
|
|
133
|
+
Mist::Post.most_popular(5).should include(subject)
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
it "should omit cr's" do
|
|
140
|
+
subject.content = "a\r\nb"
|
|
141
|
+
subject.content.should == "a\nb"
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
it "should default to draft" do
|
|
145
|
+
subject.should_not be_published
|
|
146
|
+
subject.should be_draft
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
it "should be published if publish date set" do
|
|
150
|
+
subject.published_at = Time.now
|
|
151
|
+
subject.should be_published
|
|
152
|
+
subject.should_not be_draft
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
it "should be published now" do
|
|
156
|
+
time = Time.now
|
|
157
|
+
Time.stub!(:now).and_return(time) # to account for microseconds
|
|
158
|
+
subject.published = true
|
|
159
|
+
subject.published_at.should == time
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
describe "after publication" do
|
|
163
|
+
before { subject.published = true }
|
|
164
|
+
|
|
165
|
+
it "should nil out publication date" do
|
|
166
|
+
subject.published = false
|
|
167
|
+
subject.published_at.should be_blank
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
it "should not modify publication date" do
|
|
171
|
+
time = subject.published_at
|
|
172
|
+
subject.published = true
|
|
173
|
+
subject.published_at.should == time
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
describe "with 1 code example" do
|
|
178
|
+
before do
|
|
179
|
+
FakeWeb.register_uri(:post, 'https://api.github.com/gists', :response => fixture('gist_with_1_code_example'))
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
describe "reloading the post later" do
|
|
183
|
+
before do
|
|
184
|
+
FakeWeb.register_uri(:get, 'https://api.github.com/gists/1', :response => fixture('gist_with_1_code_example'))
|
|
185
|
+
Mist::Post.create!(:title => 'Code Example', :content => "# Test Content\n\n file: test.rb\n def one\n 1\n end\n\n# Moar test content")
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
subject { Mist::Post.find('code-example') }
|
|
189
|
+
|
|
190
|
+
describe "changing its title" do
|
|
191
|
+
before { subject.title = "new title" }
|
|
192
|
+
|
|
193
|
+
it "should not change its id" do
|
|
194
|
+
subject.id.should == "code-example"
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
describe "and then saving the post" do
|
|
198
|
+
before do
|
|
199
|
+
subject.gist.should_receive(:save).and_return(true)
|
|
200
|
+
subject.save!
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
it "should update the gist's description" do
|
|
204
|
+
subject.gist.description.should =~ /new title/
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
it "should change its id" do
|
|
208
|
+
subject.id.should == "new-title"
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
describe "and then adding a new code example" do
|
|
214
|
+
before { subject.content << "\n file: moar-file.rb\n moar = :more\n\nDone" }
|
|
215
|
+
|
|
216
|
+
it "should find 2 code examples" do
|
|
217
|
+
subject.code_examples.should have(2).examples
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
it "should create a new gist file" do
|
|
221
|
+
subject.gist.should_receive(:save).and_return(true)
|
|
222
|
+
subject.save
|
|
223
|
+
subject.gist.files.should have_key('moar-file.rb')
|
|
224
|
+
subject.gist.files['moar-file.rb'].should have_key(:content)
|
|
225
|
+
subject.gist.files['moar-file.rb'][:content].should == "moar = :more\n"
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
describe "saving and then removing one code example" do
|
|
229
|
+
before do
|
|
230
|
+
subject.gist.should_receive(:save).twice.and_return(true)
|
|
231
|
+
subject.save
|
|
232
|
+
subject.content["\n file: moar-file.rb\n moar = :more\n"] = "\n"
|
|
233
|
+
subject.save
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
it "should mark moar-file.rb for deletion" do
|
|
237
|
+
subject.gist.files.should have_key('moar-file.rb')
|
|
238
|
+
subject.gist.files['moar-file.rb'].should be_nil
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
it "should not mark test.rb for deletion" do
|
|
242
|
+
subject.gist.files.should have_key('test.rb')
|
|
243
|
+
subject.gist.files['test.rb'].should_not be_nil
|
|
244
|
+
end
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
describe "and then removing the code example" do
|
|
249
|
+
before { subject.content = "no code examples here" }
|
|
250
|
+
|
|
251
|
+
it "should find 0 code examples" do
|
|
252
|
+
subject.code_examples.should be_empty
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
it "should delete the gist" do
|
|
256
|
+
subject.gist.should_receive(:destroy).and_return(true)
|
|
257
|
+
subject.save
|
|
258
|
+
end
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
describe "with the gist now missing" do
|
|
262
|
+
before do
|
|
263
|
+
FakeWeb.register_uri(:get, 'https://api.github.com/gists/1', :response => fixture('gist_404'))
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
it "should not raise an error" do
|
|
267
|
+
proc { subject }.should_not raise_error
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
it "should embed code using regular markdown" do
|
|
271
|
+
subject.content_as_html.should_not =~ /gist.github.com/
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
describe "when saving the record" do
|
|
275
|
+
it "should create a new gist" do
|
|
276
|
+
subject.save!
|
|
277
|
+
subject.gist.should be_persisted
|
|
278
|
+
end
|
|
279
|
+
end
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
it "should ensure a blank line before and after gist embeds" do
|
|
283
|
+
# otherwise not having the blanks will cause markdown to not handle headers properly
|
|
284
|
+
content = subject.content_with_embedded_gists
|
|
285
|
+
content.should =~ /\n\n<script.*?<\/script>\n\n/
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
it "should still have the gist" do
|
|
289
|
+
subject.gist.should be_persisted
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
it "should contain gist code" do
|
|
293
|
+
# so the blogger can later edit the gist.
|
|
294
|
+
# Also, if the gist is externally upated, it should be reflected
|
|
295
|
+
# when blog post is updated. This test shows as much because in
|
|
296
|
+
# the fakeweb response, 1 is switched with :one.
|
|
297
|
+
subject.content.should == "# Test Content\n\n file: test.rb\n def one\n :one\n end\n\n# Moar test content"
|
|
298
|
+
end
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
describe "constructing a new post" do
|
|
302
|
+
before do
|
|
303
|
+
subject.title = "Code Example"
|
|
304
|
+
subject.content = "# Test Content\n\n file: test.rb\n def one\n 1\n end\n\n# Moar test content"
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
describe "after saving" do
|
|
308
|
+
before do
|
|
309
|
+
subject.gist.should_receive(:save).and_return(true)
|
|
310
|
+
subject.save
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
it "should know its own url" do
|
|
314
|
+
subject.url.should == "http://example.com/posts/code-example"
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
describe "the gist description" do
|
|
318
|
+
let(:desc) { subject.gist.description }
|
|
319
|
+
|
|
320
|
+
it "include link to post" do
|
|
321
|
+
desc.should =~ /example.com\/posts\/code-example/
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
it "should not include code example filename" do
|
|
325
|
+
subject.gist.description.should_not =~ /test.rb/
|
|
326
|
+
end
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
end
|
|
330
|
+
it { should have_code_examples }
|
|
331
|
+
|
|
332
|
+
it "should embed the gist in html" do
|
|
333
|
+
subject.save!
|
|
334
|
+
embed = '<script src="https://gist.github.com/1.js?file=test.rb"></script>'
|
|
335
|
+
subject.content_as_html.should =~ /#{Regexp::escape embed}/
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
it "should not embed the gist in html preview" do
|
|
339
|
+
subject.save!
|
|
340
|
+
subject.content_as_html_preview.should_not =~ /gist.github.com/
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
it "should not embed code in html preview" do
|
|
344
|
+
subject.save!
|
|
345
|
+
subject.content_as_html_preview.should_not =~ /file: test.rb/
|
|
346
|
+
subject.content_as_html_preview.should_not =~ /def one/
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
it "should include the first line in html preview" do
|
|
350
|
+
subject.save!
|
|
351
|
+
subject.content_as_html_preview.should =~ /Test Content/
|
|
352
|
+
end
|
|
353
|
+
|
|
354
|
+
it "should not include moar content in the html preview" do
|
|
355
|
+
subject.save!
|
|
356
|
+
subject.content_as_html_preview.should_not =~ /Moar test content/
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
it "should not embed gist info if there are no code examples" do
|
|
360
|
+
subject.content = "No code"
|
|
361
|
+
subject.save!
|
|
362
|
+
subject.content_as_html.should_not =~ /gist.github.com/
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
it "should use the example's filename" do
|
|
366
|
+
# we don't want the fake response to modify the gist this time
|
|
367
|
+
subject.gist.stub(:save).and_return(true)
|
|
368
|
+
subject.save!
|
|
369
|
+
subject.gist.files.should have_key('test.rb')
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
it "should identify 1 code example" do
|
|
373
|
+
subject.code_examples.length.should == 1
|
|
374
|
+
subject.code_examples.first.should == "def one\n 1\nend\n"
|
|
375
|
+
end
|
|
376
|
+
|
|
377
|
+
it "should not have saved a gist yet" do
|
|
378
|
+
subject.gist.should_not be_persisted
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
describe "saving" do
|
|
382
|
+
it "should save a gist" do
|
|
383
|
+
subject.save!
|
|
384
|
+
subject.gist.should be_persisted
|
|
385
|
+
end
|
|
386
|
+
end
|
|
387
|
+
end
|
|
388
|
+
end
|
|
389
|
+
|
|
390
|
+
describe "with no code examples" do
|
|
391
|
+
before do
|
|
392
|
+
subject.title = "No Code Example"
|
|
393
|
+
subject.content = "# Test Content"
|
|
394
|
+
end
|
|
395
|
+
|
|
396
|
+
it { should_not have_code_examples }
|
|
397
|
+
|
|
398
|
+
it "should not have a gist at all" do
|
|
399
|
+
subject.gist.should be_nil
|
|
400
|
+
end
|
|
401
|
+
|
|
402
|
+
it "should not create a gist" do
|
|
403
|
+
subject.save!
|
|
404
|
+
subject.gist.should be_nil
|
|
405
|
+
end
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
describe "validation" do
|
|
409
|
+
before { subject.valid? }
|
|
410
|
+
|
|
411
|
+
it "should require title" do
|
|
412
|
+
subject.errors[:title].should include("can't be blank")
|
|
413
|
+
end
|
|
414
|
+
|
|
415
|
+
it "should require content" do
|
|
416
|
+
subject.errors[:content].should include("can't be blank")
|
|
417
|
+
end
|
|
418
|
+
|
|
419
|
+
it "should enforce uniqueness of title" do
|
|
420
|
+
create :post
|
|
421
|
+
post = build :post
|
|
422
|
+
post.valid?
|
|
423
|
+
post.errors[:title].should include("has already been taken")
|
|
424
|
+
end
|
|
425
|
+
end
|
|
426
|
+
|
|
427
|
+
describe "creation" do
|
|
428
|
+
it "should return the post" do
|
|
429
|
+
Mist::Post.create!(attributes_for :post).should be_kind_of(Mist::Post)
|
|
430
|
+
end
|
|
431
|
+
|
|
432
|
+
it "should not be a new record" do
|
|
433
|
+
Mist::Post.create!(attributes_for :post).should_not be_new_record
|
|
434
|
+
end
|
|
435
|
+
end
|
|
436
|
+
|
|
437
|
+
describe "new valid record" do
|
|
438
|
+
subject { build :post }
|
|
439
|
+
|
|
440
|
+
it { should_not be_persisted }
|
|
441
|
+
it { should be_new_record }
|
|
442
|
+
it { should be_changed }
|
|
443
|
+
|
|
444
|
+
describe "after saving" do
|
|
445
|
+
before { subject.save! }
|
|
446
|
+
|
|
447
|
+
it { should be_persisted }
|
|
448
|
+
it { should_not be_new_record }
|
|
449
|
+
it { should_not be_changed }
|
|
450
|
+
|
|
451
|
+
it "should increase count" do
|
|
452
|
+
Mist::Post.count.should == 1
|
|
453
|
+
end
|
|
454
|
+
|
|
455
|
+
it "should have created an attribute file" do
|
|
456
|
+
File.should be_file(subject.path)
|
|
457
|
+
end
|
|
458
|
+
|
|
459
|
+
it "should have created a commit" do
|
|
460
|
+
Mist.log.size.should == 1
|
|
461
|
+
end
|
|
462
|
+
|
|
463
|
+
it "should load the content in a separate query" do
|
|
464
|
+
Mist::Post.find(subject.id).content.should == subject.content
|
|
465
|
+
end
|
|
466
|
+
end
|
|
467
|
+
end
|
|
468
|
+
|
|
469
|
+
describe "an existing record" do
|
|
470
|
+
subject { create :post }
|
|
471
|
+
|
|
472
|
+
describe "destroying" do
|
|
473
|
+
before { subject.destroy }
|
|
474
|
+
|
|
475
|
+
it "should not be found" do
|
|
476
|
+
Mist::Post.find(subject.id).should be_nil
|
|
477
|
+
end
|
|
478
|
+
|
|
479
|
+
it "should produce a commit" do
|
|
480
|
+
Mist.log.size.should == 2
|
|
481
|
+
end
|
|
482
|
+
|
|
483
|
+
it "should reduce count" do
|
|
484
|
+
Mist::Post.count.should == 0
|
|
485
|
+
end
|
|
486
|
+
end
|
|
487
|
+
|
|
488
|
+
describe "changing its content" do
|
|
489
|
+
before { subject.content = "changed"; subject.save! }
|
|
490
|
+
|
|
491
|
+
it "should create a commit" do
|
|
492
|
+
Mist.log.size.should == 2
|
|
493
|
+
end
|
|
494
|
+
|
|
495
|
+
it "should load the new content in a separate query" do
|
|
496
|
+
Mist::Post.find(subject.id).content.should == "changed"
|
|
497
|
+
end
|
|
498
|
+
end
|
|
499
|
+
|
|
500
|
+
describe "changing its subject" do
|
|
501
|
+
before do
|
|
502
|
+
@old_path = subject.path
|
|
503
|
+
subject.title = "changed"
|
|
504
|
+
subject.save!
|
|
505
|
+
end
|
|
506
|
+
|
|
507
|
+
it "should create a commit" do
|
|
508
|
+
Mist.log.size.should == 2
|
|
509
|
+
end
|
|
510
|
+
|
|
511
|
+
it "should have changed the content path" do
|
|
512
|
+
@old_path.should_not == subject.path
|
|
513
|
+
end
|
|
514
|
+
|
|
515
|
+
it "should have removed the old content path" do
|
|
516
|
+
File.should_not exist(@old_path)
|
|
517
|
+
end
|
|
518
|
+
|
|
519
|
+
it "should hvae created a new content path" do
|
|
520
|
+
File.should be_file(subject.path)
|
|
521
|
+
end
|
|
522
|
+
end
|
|
523
|
+
|
|
524
|
+
describe "changing its subject and its content simultaneously" do
|
|
525
|
+
before do
|
|
526
|
+
@old_path = subject.path
|
|
527
|
+
subject.title = "changed"
|
|
528
|
+
subject.content = "changed"
|
|
529
|
+
subject.save!
|
|
530
|
+
end
|
|
531
|
+
|
|
532
|
+
it "should create a commit" do
|
|
533
|
+
Mist.log.size.should == 2
|
|
534
|
+
end
|
|
535
|
+
|
|
536
|
+
it "should have changed the content path" do
|
|
537
|
+
@old_path.should_not == subject.path
|
|
538
|
+
end
|
|
539
|
+
|
|
540
|
+
it "should have removed the old content path" do
|
|
541
|
+
File.should_not exist(@old_path)
|
|
542
|
+
end
|
|
543
|
+
|
|
544
|
+
it "should have created a new content path" do
|
|
545
|
+
File.should be_file(subject.path)
|
|
546
|
+
end
|
|
547
|
+
|
|
548
|
+
it "should load the new content in a separate query" do
|
|
549
|
+
Mist::Post.find(subject.id).content.should == "changed"
|
|
550
|
+
end
|
|
551
|
+
end
|
|
552
|
+
end
|
|
553
|
+
|
|
554
|
+
describe "active model lint tests" do
|
|
555
|
+
# make sure we didn't break them
|
|
556
|
+
|
|
557
|
+
include Test::Unit::Assertions
|
|
558
|
+
include ActiveModel::Lint::Tests
|
|
559
|
+
|
|
560
|
+
def model
|
|
561
|
+
@model ||= Class.new(Mist::GitModel) do
|
|
562
|
+
def self.name
|
|
563
|
+
"TestModel"
|
|
564
|
+
end
|
|
565
|
+
end.new
|
|
566
|
+
end
|
|
567
|
+
|
|
568
|
+
# to_s is to support ruby-1.9
|
|
569
|
+
ActiveModel::Lint::Tests.public_instance_methods.map{|m| m.to_s}.grep(/^test/).each do |m|
|
|
570
|
+
example m.gsub('_',' ') do
|
|
571
|
+
send m
|
|
572
|
+
end
|
|
573
|
+
end
|
|
574
|
+
end
|
|
575
|
+
end
|