dm-svn 0.2.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 +23 -0
- data/Rakefile +56 -0
- data/VERSION +1 -0
- data/dm-svn.gemspec +85 -0
- data/lib/dm-svn.rb +13 -0
- data/lib/dm-svn/config.rb +38 -0
- data/lib/dm-svn/model.rb +12 -0
- data/lib/dm-svn/svn.rb +144 -0
- data/lib/dm-svn/svn/categorized.rb +113 -0
- data/lib/dm-svn/svn/changeset.rb +119 -0
- data/lib/dm-svn/svn/node.rb +128 -0
- data/lib/dm-svn/svn/sync.rb +85 -0
- data/spec/dm-svn/config_spec.rb +51 -0
- data/spec/dm-svn/database.yml +16 -0
- data/spec/dm-svn/fixtures/articles_comments.rb +95 -0
- data/spec/dm-svn/mock_models.rb +53 -0
- data/spec/dm-svn/model_spec.rb +5 -0
- data/spec/dm-svn/spec_helper.rb +50 -0
- data/spec/dm-svn/svn/categorized_spec.rb +138 -0
- data/spec/dm-svn/svn/changeset_spec.rb +42 -0
- data/spec/dm-svn/svn/node_spec.rb +125 -0
- data/spec/dm-svn/svn/sync_spec.rb +111 -0
- data/spec/dm-svn/svn_spec.rb +213 -0
- data/spec/spec.opts +0 -0
- data/spec/spec_helper.rb +23 -0
- metadata +132 -0
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'dm-svn'
|
3
|
+
|
4
|
+
class MockArticle
|
5
|
+
include DataMapper::Resource
|
6
|
+
include DmSvn::Svn
|
7
|
+
|
8
|
+
property :id, Serial
|
9
|
+
property :title, String
|
10
|
+
property :contents, Text, :body_property => true
|
11
|
+
end
|
12
|
+
|
13
|
+
class MockArticleNoSvn
|
14
|
+
include DataMapper::Resource
|
15
|
+
|
16
|
+
property :id, Serial
|
17
|
+
property :title, String
|
18
|
+
property :contents, Text
|
19
|
+
end
|
20
|
+
|
21
|
+
class MockSyncModel
|
22
|
+
include DataMapper::Resource
|
23
|
+
include DmSvn::Svn
|
24
|
+
|
25
|
+
property :id, Serial
|
26
|
+
property :title, String
|
27
|
+
property :body, Text, :body_property => true
|
28
|
+
property :published_at, DateTime
|
29
|
+
property :random_number, Integer # because some tests need a non-datetime prop
|
30
|
+
end
|
31
|
+
|
32
|
+
class MockCategory
|
33
|
+
include DataMapper::Resource
|
34
|
+
include DmSvn::Svn
|
35
|
+
has n, :mock_categorized_articles
|
36
|
+
|
37
|
+
property :id, Serial
|
38
|
+
property :title, String
|
39
|
+
property :random_number, Integer
|
40
|
+
end
|
41
|
+
|
42
|
+
class MockCategorizedArticle
|
43
|
+
include DataMapper::Resource
|
44
|
+
include DmSvn::Svn
|
45
|
+
belongs_to :mock_category, :svn => true
|
46
|
+
|
47
|
+
property :id, Serial
|
48
|
+
property :title, String
|
49
|
+
property :article, String
|
50
|
+
property :body, Text, :body_property => true
|
51
|
+
property :published_at, DateTime
|
52
|
+
property :random_number, Integer # because some tests need a non-datetime prop
|
53
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
class MockArticle
|
2
|
+
include DataMapper::Resource
|
3
|
+
include DmSvn::Svn
|
4
|
+
|
5
|
+
property :id, Integer, :serial => true
|
6
|
+
property :title, String
|
7
|
+
property :contents, Text, :body_property => true
|
8
|
+
end
|
9
|
+
|
10
|
+
class MockArticleNoSvn
|
11
|
+
include DataMapper::Resource
|
12
|
+
|
13
|
+
property :id, Integer, :serial => true
|
14
|
+
property :title, String
|
15
|
+
property :contents, Text
|
16
|
+
end
|
17
|
+
|
18
|
+
class MockSyncModel
|
19
|
+
include DataMapper::Resource
|
20
|
+
include DmSvn::Svn
|
21
|
+
|
22
|
+
property :id, Integer, :serial => true
|
23
|
+
property :title, String
|
24
|
+
property :body, Text, :body_property => true
|
25
|
+
property :published_at, DateTime
|
26
|
+
property :random_number, Integer # because some tests need a non-datetime prop
|
27
|
+
end
|
28
|
+
|
29
|
+
class MockCategory
|
30
|
+
include DataMapper::Resource
|
31
|
+
include DmSvn::Svn
|
32
|
+
has n, :mock_categorized_articles
|
33
|
+
|
34
|
+
property :id, Integer, :serial => true
|
35
|
+
property :title, String
|
36
|
+
property :random_number, Integer
|
37
|
+
end
|
38
|
+
|
39
|
+
class MockCategorizedArticle
|
40
|
+
include DataMapper::Resource
|
41
|
+
include DmSvn::Svn
|
42
|
+
belongs_to :mock_category, :svn => true
|
43
|
+
|
44
|
+
property :id, Integer, :serial => true
|
45
|
+
property :title, String
|
46
|
+
property :article, String
|
47
|
+
property :body, Text, :body_property => true
|
48
|
+
property :published_at, DateTime
|
49
|
+
property :random_number, Integer # because some tests need a non-datetime prop
|
50
|
+
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'dm-svn/mock_models'
|
3
|
+
|
4
|
+
describe DmSvn::Svn::Categorized do
|
5
|
+
before(:all) do
|
6
|
+
DmSvn::Model.auto_migrate!
|
7
|
+
MockCategory.auto_migrate!
|
8
|
+
MockCategorizedArticle.auto_migrate!
|
9
|
+
end
|
10
|
+
|
11
|
+
before(:each) do
|
12
|
+
MockCategory.all.each { |m| m.destroy }
|
13
|
+
end
|
14
|
+
|
15
|
+
describe ".belongs_to" do
|
16
|
+
it "should initialize @svn_category" do
|
17
|
+
MockCategorizedArticle.instance_variable_get('@svn_category').should ==
|
18
|
+
:mock_category
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should initialize @svn_category_model' do
|
22
|
+
MockCategorizedArticle.instance_variable_get('@svn_category_model').should ==
|
23
|
+
'MockCategory'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
it '.svn_category should get name of category (as method name)' do
|
28
|
+
MockCategorizedArticle.svn_category.should == :mock_category
|
29
|
+
end
|
30
|
+
|
31
|
+
it '.svn_category_model should get name of category (as constant)' do
|
32
|
+
MockCategorizedArticle.svn_category_model.should == 'MockCategory'
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "#path" do
|
36
|
+
before(:each) do
|
37
|
+
@article = MockCategorizedArticle.new(:svn_name => 'article')
|
38
|
+
@category = MockCategory.new(:svn_name => 'cat/path')
|
39
|
+
@article.mock_category = @category
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should append @svn_name to svn_category.path" do
|
43
|
+
@article.path.should == 'cat/path/article'
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should return just @svn_name if svn_category.path is blank" do
|
47
|
+
@category.path = ''
|
48
|
+
@article.path.should == 'article'
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should return just @svn_name if svn_category is nil" do
|
52
|
+
@article.mock_category = nil
|
53
|
+
@article.path.should == 'article'
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "#path=" do
|
58
|
+
before(:each) do
|
59
|
+
@article = MockCategorizedArticle.new(:svn_name => 'article')
|
60
|
+
@category = MockCategory.create(:svn_name => 'cat/path')
|
61
|
+
@article.mock_category = @category
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should move instance to a different category" do
|
65
|
+
new_cat = MockCategory.create(:svn_name => 'cat/new')
|
66
|
+
@article.path = "cat/new/article"
|
67
|
+
@article.mock_category.should == new_cat
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should update @svn_name" do
|
71
|
+
@article.path = "cat/path/article2"
|
72
|
+
@article.svn_name.should == 'article2'
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should remove any category if only one path level" do
|
76
|
+
MockCategory.should_not_receive(:get_or_create)
|
77
|
+
@article.path = "article"
|
78
|
+
@article.mock_category.should be_nil
|
79
|
+
@article.path.should == 'article'
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should ignore leading slash" do
|
83
|
+
new_cat = MockCategory.create(:svn_name => 'cat/new')
|
84
|
+
MockCategory.should_receive(:get_or_create).with('cat/new')
|
85
|
+
@article.path = "//cat/new/article"
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
describe ".get" do
|
91
|
+
it "should get an instance if possible" do
|
92
|
+
MockCategorizedArticle.should_receive(:get_by_path).
|
93
|
+
with('path/to/name').
|
94
|
+
and_return(1)
|
95
|
+
|
96
|
+
MockCategorizedArticle.get('path/to/name', true) == 1
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should try to get an instance of parent if needed (and get_parent is true)" do
|
100
|
+
MockCategorizedArticle.should_receive(:get_by_path).
|
101
|
+
with('path/to/name').
|
102
|
+
and_return(nil)
|
103
|
+
|
104
|
+
MockCategory.should_receive(:get_by_path).with('path/to/name').and_return(2)
|
105
|
+
MockCategorizedArticle.get('path/to/name', true) == 2
|
106
|
+
end
|
107
|
+
|
108
|
+
it "should not try to get an instance of parent by default" do
|
109
|
+
MockCategorizedArticle.should_receive(:get_by_path).
|
110
|
+
with('path/to/name').
|
111
|
+
and_return(nil)
|
112
|
+
|
113
|
+
MockCategory.should_not_receive(:get_by_path)
|
114
|
+
|
115
|
+
MockCategorizedArticle.get('path/to/name').should be_nil
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
119
|
+
|
120
|
+
describe ".get_by_path" do
|
121
|
+
it "should scope by category" do
|
122
|
+
category = mock(MockCategory)
|
123
|
+
|
124
|
+
MockCategory.should_receive(:first).
|
125
|
+
with(:svn_name => 'path/to').
|
126
|
+
and_return(category)
|
127
|
+
|
128
|
+
category.should_receive(:id).and_return(3)
|
129
|
+
|
130
|
+
MockCategorizedArticle.should_receive(:first).
|
131
|
+
with(:svn_name => 'name', :mock_category_id => 3).
|
132
|
+
and_return(nil)
|
133
|
+
|
134
|
+
MockCategorizedArticle.get_by_path('path/to/name')
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'dm-svn/mock_models'
|
3
|
+
|
4
|
+
describe DmSvn::Svn::Changeset do
|
5
|
+
before(:all) do
|
6
|
+
DmSvn::Model.auto_migrate!
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "#short_path" do
|
10
|
+
before(:each) do
|
11
|
+
DmSvn::Model.all.each { |m| m.destroy }
|
12
|
+
sync = mock('DmSvn::Svn::Sync')
|
13
|
+
@config = DmSvn::Config.new
|
14
|
+
@config.extension = nil
|
15
|
+
@config.path_from_root = "/articles"
|
16
|
+
sync.stub!(:config).and_return @config
|
17
|
+
sync.stub!(:model).and_return nil
|
18
|
+
sync.stub!(:repos).and_return nil
|
19
|
+
|
20
|
+
@changeset = DmSvn::Svn::Changeset.new([], 1, '', Time.now, sync)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should remove 'leading path'" do
|
24
|
+
@changeset.__send__(:short_path, "/articles/something").should == "something"
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should remove extension if configured" do
|
28
|
+
@config.extension = 'txt'
|
29
|
+
@changeset.__send__(:short_path, "/articles/something.txt").should == "something"
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should not remove other extensions" do
|
33
|
+
@config.extension = 'txt'
|
34
|
+
@changeset.__send__(:short_path, "/articles/something.jpg").should == "something.jpg"
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should not remove extension if not configured" do
|
38
|
+
@changeset.__send__(:short_path, "/articles/something.txt").should == "something.txt"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'dm-svn/mock_models'
|
3
|
+
|
4
|
+
describe DmSvn::Svn::Node do
|
5
|
+
before(:all) do
|
6
|
+
@repos_uri = load_svn_fixture('articles_comments')
|
7
|
+
|
8
|
+
DmSvn::Model.auto_migrate!
|
9
|
+
@ws_model = DmSvn::Model.create(:name => 'MockSyncModel', :revision => 0)
|
10
|
+
@ws_model.config = DmSvn::Config.new
|
11
|
+
@ws_model.config.uri = @repos_uri
|
12
|
+
@sync = DmSvn::Svn::Sync.new(@ws_model)
|
13
|
+
@sync.__send__(:connect, @repos_uri)
|
14
|
+
|
15
|
+
@cs = @sync.changesets[1] # revision 2
|
16
|
+
@cs3 = @sync.changesets[2] # revision 9
|
17
|
+
@cs9 = @sync.changesets[7] # revision 9
|
18
|
+
@dir = DmSvn::Svn::Node.new(@cs, "/articles")
|
19
|
+
@file = DmSvn::Svn::Node.new(@cs3, "/articles/unpublished.txt")
|
20
|
+
end
|
21
|
+
|
22
|
+
after(:all) do
|
23
|
+
SvnFixture::Repository.destroy_all
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should get short_path" do
|
27
|
+
@file.short_path.should == "unpublished"
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should check if file" do
|
31
|
+
@dir.file?.should be_false
|
32
|
+
@file.file?.should be_true
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should check if directory" do
|
36
|
+
@dir.directory?.should be_true
|
37
|
+
@file.directory?.should be_false
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should get body" do
|
41
|
+
@dir.body.should be_nil
|
42
|
+
@file.body.should == "See, it's not published.\nYou can't read it."
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should remove yaml from body" do
|
46
|
+
DmSvn::Svn::Node.new(@cs9, "/articles/turtle.txt").body.should == 'Hi, turtle.'
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "#properties" do
|
50
|
+
it "should get properties from svn properties" do
|
51
|
+
@dir.properties.should ==
|
52
|
+
{
|
53
|
+
'svn_updated_at' => @dir.date,
|
54
|
+
'svn_updated_by' => @dir.author,
|
55
|
+
'svn_updated_rev' => @dir.revision,
|
56
|
+
'title' => 'Articles'
|
57
|
+
}
|
58
|
+
|
59
|
+
@file.properties.should ==
|
60
|
+
{
|
61
|
+
'svn_updated_at' => @file.date,
|
62
|
+
'svn_updated_by' => @file.author,
|
63
|
+
'svn_updated_rev' => @file.revision,
|
64
|
+
'title' => 'Private Thoughts'
|
65
|
+
}
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should get properties from yaml properties" do
|
70
|
+
dir9 = DmSvn::Svn::Node.new(@cs9, "/articles")
|
71
|
+
dir9.properties.should ==
|
72
|
+
{
|
73
|
+
'svn_updated_at' => dir9.date,
|
74
|
+
'svn_updated_by' => dir9.author,
|
75
|
+
'svn_updated_rev' => dir9.revision,
|
76
|
+
'title' => 'Lots of Articles',
|
77
|
+
'random_number' => 7
|
78
|
+
}
|
79
|
+
|
80
|
+
file9 = DmSvn::Svn::Node.new(@cs9, "/articles/turtle.txt")
|
81
|
+
file9.properties.should ==
|
82
|
+
{
|
83
|
+
'svn_updated_at' => file9.date,
|
84
|
+
'svn_updated_by' => file9.author,
|
85
|
+
'svn_updated_rev' => file9.revision,
|
86
|
+
'title' => 'Turtle',
|
87
|
+
'random_number' => 2
|
88
|
+
}
|
89
|
+
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
describe "variables from changeset" do
|
94
|
+
before(:each) do
|
95
|
+
@cs = mock(DmSvn::Svn::Changeset)
|
96
|
+
@node = DmSvn::Svn::Node.new(@cs, 'path')
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should get revision" do
|
100
|
+
@cs.should_receive(:revision).and_return(2)
|
101
|
+
@node.revision.should == 2
|
102
|
+
end
|
103
|
+
|
104
|
+
it "should get author" do
|
105
|
+
@cs.should_receive(:author).and_return('jmorgan')
|
106
|
+
@node.author.should == 'jmorgan'
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should get date" do
|
110
|
+
@cs.should_receive(:date).and_return('2008-05-10')
|
111
|
+
@node.date.should == '2008-05-10'
|
112
|
+
end
|
113
|
+
|
114
|
+
it "should get repos" do
|
115
|
+
@cs.should_receive(:repos).and_return(:repos)
|
116
|
+
@node.repos.should == :repos
|
117
|
+
end
|
118
|
+
|
119
|
+
it "should get config" do
|
120
|
+
@cs.should_receive(:config).and_return(:config)
|
121
|
+
@node.config.should == :config
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'dm-svn/mock_models'
|
3
|
+
|
4
|
+
describe DmSvn::Svn::Sync do
|
5
|
+
after(:all) do
|
6
|
+
SvnFixture::Repository.destroy_all
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "#run" do
|
10
|
+
before(:all) do
|
11
|
+
DmSvn::Model.auto_migrate!
|
12
|
+
MockSyncModel.auto_migrate!
|
13
|
+
@repos_uri = load_svn_fixture('articles_comments')
|
14
|
+
end
|
15
|
+
|
16
|
+
before(:each) do
|
17
|
+
MockSyncModel.all.each { |m| m.destroy }
|
18
|
+
DmSvn::Model.all.each { |m| m.destroy }
|
19
|
+
@ws_model = DmSvn::Model.create(:name => 'MockSyncModel', :revision => 0)
|
20
|
+
@ws_model.config = DmSvn::Config.new
|
21
|
+
@ws_model.config.uri = @repos_uri
|
22
|
+
@sync = DmSvn::Svn::Sync.new(@ws_model)
|
23
|
+
end
|
24
|
+
|
25
|
+
# This is a generic "it should just work" test
|
26
|
+
it "should update database" do
|
27
|
+
@sync.run
|
28
|
+
MockSyncModel.count.should == 4
|
29
|
+
|
30
|
+
comp = MockSyncModel.first(:svn_name => "computations")
|
31
|
+
comp.body.should == 'Computers do not like salsa very much.'
|
32
|
+
comp.svn_updated_rev.to_i.should == 7
|
33
|
+
comp.svn_created_rev.to_i.should == 7
|
34
|
+
|
35
|
+
phil = MockSyncModel.first(:svn_name => "philosophy")
|
36
|
+
phil.svn_updated_rev.to_i.should == 2
|
37
|
+
phil.svn_created_rev.to_i.should == 2
|
38
|
+
|
39
|
+
pub = MockSyncModel.first(:svn_name => "just_published")
|
40
|
+
published_time = Time.parse(pub.published_at.strftime("%Y-%m-%d %H:%M:%S"))
|
41
|
+
published_time.should be_close(Time.now - 3600, 100)
|
42
|
+
pub.svn_created_by.should == "author"
|
43
|
+
pub.title.should == "Private Thoughts"
|
44
|
+
pub.svn_updated_rev.to_i.should == 7
|
45
|
+
pub.svn_created_rev.to_i.should == 3
|
46
|
+
|
47
|
+
MockSyncModel.first(:svn_name => "computers.txt").should be_nil
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should update DmSvn::Model entry" do
|
51
|
+
@sync.run
|
52
|
+
DmSvn::Model.get(@ws_model.id).revision.should == 9
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should return false if already at the youngest revision" do
|
56
|
+
@sync.run.should be_true
|
57
|
+
@ws_model = DmSvn::Model.get(@ws_model.id)
|
58
|
+
@ws_model.config = DmSvn::Config.new
|
59
|
+
@ws_model.config.uri = @repos_uri
|
60
|
+
@sync = DmSvn::Svn::Sync.new(@ws_model)
|
61
|
+
@sync.run.should be_false
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe "#run (categorized)" do
|
66
|
+
before(:all) do
|
67
|
+
DmSvn::Model.auto_migrate!
|
68
|
+
MockCategory.auto_migrate!
|
69
|
+
MockCategorizedArticle.auto_migrate!
|
70
|
+
@repos_uri = load_svn_fixture('articles_comments')[0..-10]
|
71
|
+
end
|
72
|
+
|
73
|
+
before(:each) do
|
74
|
+
MockCategory.all.each { |m| m.destroy }
|
75
|
+
MockCategorizedArticle.all.each { |m| m.destroy }
|
76
|
+
DmSvn::Model.all.each { |m| m.destroy }
|
77
|
+
@ws_model = DmSvn::Model.create(:name => 'MockCategorizedArticle', :revision => 0)
|
78
|
+
@ws_model.config = DmSvn::Config.new
|
79
|
+
@ws_model.config.uri = @repos_uri
|
80
|
+
@sync = DmSvn::Svn::Sync.new(@ws_model)
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should update database, when categorized" do
|
84
|
+
@sync.run
|
85
|
+
|
86
|
+
MockCategory.count.should == 2
|
87
|
+
MockCategorizedArticle.count.should == 6
|
88
|
+
|
89
|
+
comp = MockCategorizedArticle.first(:svn_name => "computations")
|
90
|
+
comp.body.should == 'Computers do not like salsa very much.'
|
91
|
+
comp.svn_updated_rev.to_i.should == 7
|
92
|
+
comp.svn_created_rev.to_i.should == 7
|
93
|
+
|
94
|
+
phil = MockCategorizedArticle.first(:svn_name => "philosophy")
|
95
|
+
phil.svn_updated_rev.to_i.should == 2
|
96
|
+
phil.svn_created_rev.to_i.should == 2
|
97
|
+
|
98
|
+
MockCategorizedArticle.first(:svn_name => "computers.txt").should be_nil
|
99
|
+
|
100
|
+
articles = MockCategory.first(:svn_name => "articles")
|
101
|
+
articles.mock_categorized_articles.length.should == 4
|
102
|
+
comp.mock_category.id.should == articles.id
|
103
|
+
articles.title.should == "Lots of Articles"
|
104
|
+
|
105
|
+
comments = MockCategory.first(:svn_name => "comments")
|
106
|
+
comments.mock_categorized_articles.length.should == 2
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|