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.
@@ -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,5 @@
1
+ require 'spec_helper'
2
+
3
+ describe DmSvn::Model do
4
+
5
+ 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