gdocs_features 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +0 -0
- data/Rakefile +35 -0
- data/VERSION +1 -0
- data/bin/remotefeatures +7 -0
- data/cucumber.yml +2 -0
- data/features/patch_local_files_from_gdocs.feature +33 -0
- data/features/step_definitions/diff_steps.rb +19 -0
- data/features/step_definitions/google_steps.rb +19 -0
- data/features/step_definitions/local_steps.rb +16 -0
- data/features/support/env.rb +5 -0
- data/gdocs_features.gemspec +97 -0
- data/lib/difference.rb +31 -0
- data/lib/feature.rb +26 -0
- data/lib/feature_diff.rb +46 -0
- data/lib/file_feature.rb +37 -0
- data/lib/file_feature_store.rb +17 -0
- data/lib/google_authorization.rb +18 -0
- data/lib/google_docs_client.rb +20 -0
- data/lib/google_feature.rb +51 -0
- data/lib/google_feature_store.rb +44 -0
- data/lib/google_resource.rb +11 -0
- data/lib/remote_features/cli/main.rb +30 -0
- data/lib/remote_features/dialogue.rb +25 -0
- data/pkg/gdocs_features-0.1.0.gem +0 -0
- data/spec/cli_spec.rb +69 -0
- data/spec/dialogue_spec.rb +69 -0
- data/spec/feature_diff_spec.rb +80 -0
- data/spec/feature_reformat_spec.rb +40 -0
- data/spec/file_feature_spec.rb +23 -0
- data/spec/file_feature_store_spec.rb +33 -0
- data/spec/google_authorization_spec.rb +26 -0
- data/spec/google_docs_client_spec.rb +32 -0
- data/spec/google_feature_spec.rb +46 -0
- data/spec/google_feature_store_spec.rb +64 -0
- data/spec/google_resource_spec.rb +25 -0
- data/spec/integration_spec.rb +42 -0
- data/spec/spec_helper.rb +5 -0
- data/spec/stubs/documents.atom.xml +36 -0
- data/spec/stubs/example.feature +16 -0
- data/spec/stubs/folders.atom.xml +69 -0
- data/spec/temp_file_system.rb +19 -0
- data/spec/temp_file_system_spec.rb +28 -0
- metadata +117 -0
data/spec/cli_spec.rb
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
require 'file_feature_store'
|
4
|
+
require 'google_feature_store'
|
5
|
+
require 'remote_features/cli/main'
|
6
|
+
require 'remote_features/dialogue'
|
7
|
+
|
8
|
+
describe RemoteFeatures::Cli::Main do
|
9
|
+
before do
|
10
|
+
$stdout.stub!(:puts)
|
11
|
+
Kernel.stub!(:exit)
|
12
|
+
RemoteFeatures::Dialogue.stub!(:new).and_return(mock("dialogue", :start => nil))
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should create a file feature store with the first argument as the path" do
|
16
|
+
file_store = mock("file_store")
|
17
|
+
gdocs_store = mock("gdocs_store")
|
18
|
+
FileFeatureStore.should_receive(:new).with("some/dir").and_return(file_store)
|
19
|
+
GoogleFeatureStore.stub!(:new).and_return(gdocs_store)
|
20
|
+
RemoteFeatures::Cli::Main.execute(["some/dir", "joshski:pass@docs.google.com"])
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should create a google feature store when argument 2 matches user:pass@docs.google.com" do
|
24
|
+
file_store = mock("file_store")
|
25
|
+
gdocs_store = mock("gdocs_store")
|
26
|
+
client = mock("client")
|
27
|
+
FileFeatureStore.stub!(:new).and_return(file_store)
|
28
|
+
GoogleDocsClient.should_receive(:new).with("joshski", "pass").and_return(client)
|
29
|
+
GoogleFeatureStore.should_receive(:new).with(client).and_return(gdocs_store)
|
30
|
+
RemoteFeatures::Cli::Main.execute(["some/dir", "joshski:pass@docs.google.com"])
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "with invalid arguments", :shared => true do
|
34
|
+
it "should show usage" do
|
35
|
+
[FileFeatureStore, GoogleFeatureStore, GoogleDocsClient].each { |c| c.stub!(:new) }
|
36
|
+
$stdout.should_receive(:puts).with("Usage: remotefeatures <directory> <user:password@host>")
|
37
|
+
RemoteFeatures::Cli::Main.execute(@args)
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should not create anything" do
|
41
|
+
[FileFeatureStore, GoogleFeatureStore, GoogleDocsClient].each do |c|
|
42
|
+
c.should_not_receive(:new)
|
43
|
+
end
|
44
|
+
RemoteFeatures::Cli::Main.execute(@args)
|
45
|
+
RemoteFeatures::Dialogue.should_not_receive(:new)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "with no arguments" do
|
50
|
+
before { @args = [] }
|
51
|
+
it_should_behave_like "with invalid arguments"
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "with only first argument" do
|
55
|
+
before { @args = ["."] }
|
56
|
+
it_should_behave_like "with invalid arguments"
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "with three arguments" do
|
60
|
+
before { @args = ["valid", "valid:valid@valid.com", "invalid"] }
|
61
|
+
it_should_behave_like "with invalid arguments"
|
62
|
+
end
|
63
|
+
|
64
|
+
describe "with invalid url argument" do
|
65
|
+
before { @args = ["valid", "in-valid@valid.com"] }
|
66
|
+
it_should_behave_like "with invalid arguments"
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
require 'remote_features/dialogue'
|
4
|
+
require 'feature_diff'
|
5
|
+
|
6
|
+
describe RemoteFeatures::Dialogue do
|
7
|
+
|
8
|
+
before do
|
9
|
+
@local_store = mock("local_store")
|
10
|
+
@remote_store = mock("remote_store")
|
11
|
+
@io = mock("io", :puts => nil, :gets => "")
|
12
|
+
@diff = mock("diff", :differences => {}, :patch => nil)
|
13
|
+
@dialogue = RemoteFeatures::Dialogue.new(@io, @io, @local_store, @remote_store)
|
14
|
+
FeatureDiff.stub!(:new).with(@local_store, @remote_store).and_return(@diff)
|
15
|
+
|
16
|
+
@first_local_feature = mock("first_local_feature", :path => 'first/example.feature')
|
17
|
+
@first_remote_feature = mock("first_remote_feature", :path => 'first/example.feature')
|
18
|
+
@second_local_feature = mock("second_local_feature", :path => 'second/example.feature')
|
19
|
+
@second_remote_feature = mock("second_remote_feature", :path => 'second/example.feature')
|
20
|
+
@first_difference = Difference.new(@first_local_feature, @first_remote_feature, @local_store)
|
21
|
+
@second_difference = Difference.new(@second_local_feature, @second_remote_feature, @local_store)
|
22
|
+
@diff.stub!(:differences).and_return({
|
23
|
+
@first_difference.path => @first_difference,
|
24
|
+
@second_difference.path => @second_difference
|
25
|
+
})
|
26
|
+
@expected_diff_output = "1) updated - first/example.feature\n2) updated - second/example.feature"
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should perform a feature diff" do
|
30
|
+
FeatureDiff.should_receive(:new).with(@local_store, @remote_store).and_return(@diff)
|
31
|
+
@dialogue.start
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should render the results of the feature diff to the output" do
|
35
|
+
@io.should_receive(:puts).with(@expected_diff_output)
|
36
|
+
@dialogue.start
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should prompt for patch numbers to apply" do
|
40
|
+
@io.stub!(:puts).with(@expected_diff_output)
|
41
|
+
@io.should_receive(:puts).with("Enter changes to apply, 'all' to apply all, or blank to exit")
|
42
|
+
@dialogue.start
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should accept a list of change numbers to apply" do
|
46
|
+
@io.should_receive(:gets).and_return("1 67 99\n")
|
47
|
+
@dialogue.start
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should apply the selected patches" do
|
51
|
+
@io.stub!(:gets).and_return("1 67 99\n")
|
52
|
+
@diff.should_receive(:patch).with([1, 67, 99])
|
53
|
+
@dialogue.start
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should exit when there are no differences" do
|
57
|
+
@diff.stub!(:differences).and_return({})
|
58
|
+
Kernel.should_receive(:exit)
|
59
|
+
@dialogue.start
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should write a message when there are no differences" do
|
63
|
+
@diff.stub!(:differences).and_return({})
|
64
|
+
Kernel.stub!(:exit)
|
65
|
+
@io.should_receive(:puts)
|
66
|
+
@dialogue.start
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
require 'feature_diff'
|
4
|
+
require 'google_docs_client'
|
5
|
+
require 'google_feature_store'
|
6
|
+
require 'file_feature_store'
|
7
|
+
|
8
|
+
describe FeatureDiff do
|
9
|
+
|
10
|
+
it "should find updated features where versions are different" do
|
11
|
+
local_feature = mock("local_feature", :path => '/the/same.feature', :version => '123')
|
12
|
+
remote_feature = mock("remote_feature", :path => '/the/same.feature', :version => '124')
|
13
|
+
local_store = mock("local_store", :features => [local_feature])
|
14
|
+
remote_store = mock("remote_store", :features => [remote_feature])
|
15
|
+
diff = FeatureDiff.new(local_store, remote_store)
|
16
|
+
diff['/the/same.feature'].local.should == local_feature
|
17
|
+
diff['/the/same.feature'].remote.should == remote_feature
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should find remote only features" do
|
21
|
+
remote_feature = mock("remote_feature", :path => '/remote/only.feature', :version => '123')
|
22
|
+
local_store = mock("local_store", :features => [])
|
23
|
+
remote_store = mock("remote_store", :features => [remote_feature])
|
24
|
+
diff = FeatureDiff.new(local_store, remote_store)
|
25
|
+
diff['/remote/only.feature'].remote.should == remote_feature
|
26
|
+
diff['/remote/only.feature'].local.should be_nil
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should find local only features" do
|
30
|
+
local_feature = mock("local_feature", :path => '/local/only.feature', :version => '123')
|
31
|
+
local_store = mock("local_store", :features => [local_feature])
|
32
|
+
remote_store = mock("remote_store", :features => [])
|
33
|
+
diff = FeatureDiff.new(local_store, remote_store)
|
34
|
+
diff['/local/only.feature'].local.should == local_feature
|
35
|
+
diff['/local/only.feature'].remote.should be_nil
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should patch remote only features" do
|
39
|
+
remote_feature = mock("remote_feature", :path => 'any/old.feature', :version => '789', :reformat => 'OK!')
|
40
|
+
local_store = mock("local_store", :features => [])
|
41
|
+
remote_store = mock("remote_store", :features => [remote_feature])
|
42
|
+
diff = FeatureDiff.new(local_store, remote_store)
|
43
|
+
local_store.should_receive(:create_feature).with('any/old.feature', '789', 'OK!')
|
44
|
+
diff.patch
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should patch updated features" do
|
48
|
+
local_feature = mock("local_feature", :path => '/the/same.feature', :version => '123')
|
49
|
+
remote_feature = mock("remote_feature", :path => '/the/same.feature', :version => '124')
|
50
|
+
local_store = mock("local_store", :features => [local_feature])
|
51
|
+
remote_store = mock("remote_store", :features => [remote_feature])
|
52
|
+
diff = FeatureDiff.new(local_store, remote_store)
|
53
|
+
local_feature.should_receive(:patch_from).with(remote_feature)
|
54
|
+
diff.patch
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should patch subset of differences" do
|
58
|
+
local_one = mock("local_one", :path => '/the/one.feature', :version => '123')
|
59
|
+
local_two = mock("local_two", :path => '/the/two.feature', :version => '123')
|
60
|
+
remote_one = mock("remote_one", :path => '/the/one.feature', :version => 'higher')
|
61
|
+
remote_two = mock("remote_two", :path => '/the/two.feature', :version => 'higher')
|
62
|
+
local_store = mock("local_store", :features => [local_one, local_two])
|
63
|
+
remote_store = mock("remote_store", :features => [remote_one, remote_two])
|
64
|
+
diff = FeatureDiff.new(local_store, remote_store)
|
65
|
+
local_one.should_receive(:patch_from).with(remote_one)
|
66
|
+
local_two.should_not_receive(:patch_from).with(remote_two)
|
67
|
+
diff.patch([1])
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should not patch local only features" do
|
71
|
+
local_feature = mock("local_feature", :path => '/the/same.feature', :version => '123')
|
72
|
+
local_store = mock("local_store", :features => [local_feature])
|
73
|
+
remote_store = mock("remote_store", :features => [])
|
74
|
+
diff = FeatureDiff.new(local_store, remote_store)
|
75
|
+
local_feature.should_not_receive(:patch_from)
|
76
|
+
diff.patch
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
$reformatted = %{Feature: Washing up
|
4
|
+
|
5
|
+
In order to reduce infection
|
6
|
+
As a user of kitchenware
|
7
|
+
I want to wash up after use
|
8
|
+
|
9
|
+
Scenario: Wash dishes
|
10
|
+
|
11
|
+
Given there is a dish
|
12
|
+
And it is dirty
|
13
|
+
Then I should wash it up
|
14
|
+
|
15
|
+
Scenario: Dishwasher
|
16
|
+
|
17
|
+
Given there are lots of dirty dishes
|
18
|
+
When I put them into the dishwasher
|
19
|
+
And I turn it on
|
20
|
+
Then it should wash the dishes}
|
21
|
+
|
22
|
+
require 'feature'
|
23
|
+
|
24
|
+
describe Feature, "reformat" do
|
25
|
+
|
26
|
+
class StubFeature < Feature
|
27
|
+
def body
|
28
|
+
$reformatted.map { |line| line.strip }.reject { |l| l == "" }
|
29
|
+
end
|
30
|
+
|
31
|
+
def version
|
32
|
+
123
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should reformat feature body" do
|
37
|
+
StubFeature.new.reformat.should == $reformatted
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
require 'file_feature'
|
4
|
+
|
5
|
+
describe FileFeature do
|
6
|
+
|
7
|
+
before do
|
8
|
+
@feature = FileFeature.new(File.dirname(__FILE__), "stubs/example.feature")
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should expose a body from the file" do
|
12
|
+
@feature.body.first.should == "Feature: Example"
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should expose a title from the filename" do
|
16
|
+
@feature.title.should == "example"
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should get the version from the first line of comment in the file" do
|
20
|
+
@feature.version.should == "123"
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
require File.dirname(__FILE__) + '/temp_file_system'
|
3
|
+
|
4
|
+
require 'file_feature_store'
|
5
|
+
|
6
|
+
describe FileFeatureStore do
|
7
|
+
|
8
|
+
before do
|
9
|
+
@fs = TempFileSystem.new(
|
10
|
+
'my/stuff/banana.feature' => 'OK'
|
11
|
+
)
|
12
|
+
end
|
13
|
+
|
14
|
+
after do
|
15
|
+
@fs.destroy
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should find files with .feature extension" do
|
19
|
+
store = FileFeatureStore.new("/some/dir")
|
20
|
+
Dir.should_receive(:glob).with("/some/dir/**/*.feature").and_return([])
|
21
|
+
store.features
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "with a physical file store" do
|
25
|
+
|
26
|
+
it "should find features" do
|
27
|
+
store = FileFeatureStore.new(@fs.root)
|
28
|
+
store.features.first.title.should == "banana"
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
require 'google_authorization'
|
4
|
+
|
5
|
+
describe GoogleAuthorization do
|
6
|
+
|
7
|
+
it "should post to the authorization resource once on first access of header" do
|
8
|
+
RestClient.stub!(:post).and_return("xxxAuth=ABC")
|
9
|
+
auth = GoogleAuthorization.new("email", "pass")
|
10
|
+
auth.header.should == "GoogleLogin auth=ABC"
|
11
|
+
RestClient.stub!(:post).and_raise "shouldn't post twice"
|
12
|
+
auth.header
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should post the correct url and parameters when authorizing" do
|
16
|
+
url = "https://www.google.com/accounts/ClientLogin"
|
17
|
+
params = { "accountType" => "HOSTED_OR_GOOGLE", "Email" => "email", "Passwd" => "pass", "service" => "writely" }
|
18
|
+
RestClient.should_receive(:post).with(url, hash_including(params))
|
19
|
+
GoogleAuthorization.new("email", "pass").authorize
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should authorize with a real rest client" do
|
23
|
+
GoogleAuthorization.new("restapitest@googlemail.com", "testrestapi").authorize.size.should > 100
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
require 'google_docs_client'
|
4
|
+
|
5
|
+
describe GoogleDocsClient do
|
6
|
+
|
7
|
+
it "should get the documents feed as a resource" do
|
8
|
+
client = GoogleDocsClient.new("restapitest", "testrestapi")
|
9
|
+
resource = mock("resource")
|
10
|
+
GoogleResource.should_receive(:new).and_return(resource)
|
11
|
+
resource.should_receive(:get).and_return("OK")
|
12
|
+
client.documents_feed.get.to_s.should == "OK"
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "connected to Google" do
|
16
|
+
|
17
|
+
before do
|
18
|
+
@client = GoogleDocsClient.new("restapitest@googlemail.com", "testrestapi")
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should get the documents feed" do
|
22
|
+
@client.documents_feed.get.to_s.should =~ /<feed/
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should get folders" do
|
26
|
+
@client.folders.get.to_s.should =~ /<feed/
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
$reformatted = %{Feature: Washing up
|
4
|
+
|
5
|
+
In order to reduce infection
|
6
|
+
As a user of kitchenware
|
7
|
+
I want to wash up after use
|
8
|
+
|
9
|
+
Scenario: Wash dishes
|
10
|
+
|
11
|
+
Given there is a dish
|
12
|
+
And it is dirty
|
13
|
+
Then I should wash it up
|
14
|
+
|
15
|
+
Scenario: Dishwasher
|
16
|
+
|
17
|
+
Given there are lots of dirty dishes
|
18
|
+
When I put them into the dishwasher
|
19
|
+
And I turn it on
|
20
|
+
Then it should wash the dishes}
|
21
|
+
|
22
|
+
require 'google_feature'
|
23
|
+
|
24
|
+
describe Feature, "reformat" do
|
25
|
+
|
26
|
+
class StubFeature < GoogleFeature
|
27
|
+
def body
|
28
|
+
$reformatted.map { |line| line.strip }.reject { |l| l == "" }
|
29
|
+
end
|
30
|
+
|
31
|
+
def version
|
32
|
+
123
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should reformat feature body" do
|
37
|
+
it "should not have css in the file" do
|
38
|
+
auth = mock("auth", :header => "xxx")
|
39
|
+
RestClient.should_receive(:get).with("url", hash_including("Authorization" => "xxx"))
|
40
|
+
GoogleFeature.new(auth, "url").get
|
41
|
+
|
42
|
+
end
|
43
|
+
StubFeature.new.reformat.should == $reformatted
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
require 'google_feature_store'
|
4
|
+
require 'google_docs_client'
|
5
|
+
|
6
|
+
def relative_path(path)
|
7
|
+
File.join(File.dirname(__FILE__), path)
|
8
|
+
end
|
9
|
+
|
10
|
+
def stub_folders_feed
|
11
|
+
mock("folders_feed", :get => File.readlines(relative_path('./stubs/folders.atom.xml')).map {|l| l.rstrip})
|
12
|
+
end
|
13
|
+
|
14
|
+
def stub_documents_feed
|
15
|
+
mock("documents_feed", :get => File.readlines(relative_path('./stubs/documents.atom.xml')).map {|l| l.rstrip})
|
16
|
+
end
|
17
|
+
|
18
|
+
describe GoogleFeatureStore do
|
19
|
+
|
20
|
+
describe "creating features from feed" do
|
21
|
+
|
22
|
+
before do
|
23
|
+
@body = "happy"
|
24
|
+
client = mock("client",
|
25
|
+
:folders => stub_folders_feed,
|
26
|
+
:documents_feed => stub_documents_feed,
|
27
|
+
:document_body => mock("document_body", :get => @body))
|
28
|
+
@features = GoogleFeatureStore.new(client).features
|
29
|
+
@banana = @features.first
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should expose a list of features" do
|
33
|
+
@features.size.should == 1
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should expose a body from a resource" do
|
37
|
+
@banana.body.should == [@body]
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should expose a body from the entry" do
|
41
|
+
@banana.title.should == "banana"
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should expose a version from the entry modified date" do
|
45
|
+
@banana.version.should == "2009-02-19T23:36:34.402Z"
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should get a folder hierarchy from a feed" do
|
51
|
+
client = mock("client", :folders => stub_folders_feed, :documents_feed => stub_documents_feed)
|
52
|
+
folders = GoogleFeatureStore.new(client).folders
|
53
|
+
yellow = "http://docs.google.com/feeds/documents/private/full/folder%3Aa58446b0-772d-4ff7-bcb5-eb280b0cf53a"
|
54
|
+
folders[yellow].should == "fruit/yellow"
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should attach paths to features" do
|
58
|
+
client = mock("client", :folders => stub_folders_feed, :documents_feed => stub_documents_feed)
|
59
|
+
features = GoogleFeatureStore.new(client).features
|
60
|
+
features.find_all { | f | f.path == "fruit/yellow/banana.feature" }.size.should == 1
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
require 'google_resource'
|
4
|
+
|
5
|
+
describe GoogleResource do
|
6
|
+
|
7
|
+
it "should include the authorization header on get" do
|
8
|
+
auth = mock("auth", :header => "xxx")
|
9
|
+
RestClient.should_receive(:get).with("url", hash_including("Authorization" => "xxx"))
|
10
|
+
GoogleResource.new(auth, "url").get
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should include additional headers on get" do
|
14
|
+
auth = mock("auth", :header => "xxx")
|
15
|
+
RestClient.should_receive(:get).with("url", hash_including("another" => "zzz"))
|
16
|
+
GoogleResource.new(auth, "url").get("another" => "zzz")
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should include constructor headers on get" do
|
20
|
+
auth = mock("auth", :header => "xxx")
|
21
|
+
RestClient.should_receive(:get).with("url", hash_including("another" => "zzz"))
|
22
|
+
GoogleResource.new(auth, "url", {"another" => "zzz"}).get
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
require File.dirname(__FILE__) + '/temp_file_system'
|
3
|
+
|
4
|
+
require 'google_feature_store'
|
5
|
+
require 'google_docs_client'
|
6
|
+
require 'file_feature_store'
|
7
|
+
require 'feature_diff'
|
8
|
+
|
9
|
+
describe "integration with Google" do
|
10
|
+
|
11
|
+
before(:all) do
|
12
|
+
@client = GoogleDocsClient.new("restapitest@googlemail.com", "testrestapi")
|
13
|
+
@remote_store = GoogleFeatureStore.new(@client)
|
14
|
+
@features = @remote_store.features
|
15
|
+
@fs = TempFileSystem.new(
|
16
|
+
'fruit/yellow/banana.feature' => %{#version:123
|
17
|
+
Some other text
|
18
|
+
}
|
19
|
+
)
|
20
|
+
end
|
21
|
+
|
22
|
+
after(:all) do
|
23
|
+
@fs.destroy
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should get features" do
|
27
|
+
@features.size.should > 1
|
28
|
+
banana = @features.find { |f| f.title == "banana" }
|
29
|
+
banana.path.should == 'fruit/yellow/banana.feature'
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should patch differences" do
|
33
|
+
local_store = FileFeatureStore.new(@fs.root)
|
34
|
+
diff = FeatureDiff.new(local_store, @remote_store)
|
35
|
+
banana = diff["fruit/yellow/banana.feature"]
|
36
|
+
banana.local.version.should == "123"
|
37
|
+
banana.remote.version.should_not == "123"
|
38
|
+
banana.patch
|
39
|
+
banana.local.version.should == banana.remote.version
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/" xmlns:gd="http://schemas.google.com/g/2005">
|
3
|
+
<id>http://docs.google.com/feeds/documents/private/full</id>
|
4
|
+
<updated>2009-02-19T23:42:26.569Z</updated>
|
5
|
+
<title type="text">Available Documents - restapitest@googlemail.com</title>
|
6
|
+
<link rel="alternate" type="text/html" href="http://docs.google.com"/>
|
7
|
+
<link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://docs.google.com/feeds/documents/private/full"/>
|
8
|
+
<link rel="http://schemas.google.com/g/2005#post" type="application/atom+xml" href="http://docs.google.com/feeds/documents/private/full"/>
|
9
|
+
<link rel="self" type="application/atom+xml" href="http://docs.google.com/feeds/documents/private/full"/>
|
10
|
+
<author>
|
11
|
+
<name>restapitest</name>
|
12
|
+
<email>restapitest@googlemail.com</email>
|
13
|
+
</author>
|
14
|
+
<openSearch:totalResults>1</openSearch:totalResults>
|
15
|
+
<openSearch:startIndex>1</openSearch:startIndex>
|
16
|
+
<entry>
|
17
|
+
<id>http://docs.google.com/feeds/documents/private/full/document%3Adhmn2mkk_0d4rbv8d8</id>
|
18
|
+
<published>2009-02-19T23:04:11.560Z</published>
|
19
|
+
<updated>2009-02-19T23:36:34.402Z</updated>
|
20
|
+
<category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/docs/2007#document" label="document"/>
|
21
|
+
<category scheme="http://schemas.google.com/docs/2007/folders/restapitest@googlemail.com" term="yellow" label="yellow"/>
|
22
|
+
<title type="text">Banana</title>
|
23
|
+
<content type="text/html" src="http://docs.google.com/feeds/download/documents/RawDocContents?action=fetch&justBody=false&revision=_latest&editMode=false&docID=dhmn2mkk_0d4rbv8d8"/>
|
24
|
+
<link rel="http://schemas.google.com/docs/2007#parent" type="application/atom+xml" href="http://docs.google.com/feeds/documents/private/full/folder%3Aa58446b0-772d-4ff7-bcb5-eb280b0cf53a" title="yellow"/>
|
25
|
+
<link rel="alternate" type="text/html" href="http://docs.google.com/Doc?id=dhmn2mkk_0d4rbv8d8"/>
|
26
|
+
<link rel="self" type="application/atom+xml" href="http://docs.google.com/feeds/documents/private/full/document%3Adhmn2mkk_0d4rbv8d8"/>
|
27
|
+
<link rel="edit" type="application/atom+xml" href="http://docs.google.com/feeds/documents/private/full/document%3Adhmn2mkk_0d4rbv8d8/fre2o3fm"/>
|
28
|
+
<link rel="edit-media" type="text/html" href="http://docs.google.com/feeds/media/private/full/document%3Adhmn2mkk_0d4rbv8d8/fre2o3fm"/>
|
29
|
+
<author>
|
30
|
+
<name>restapitest</name>
|
31
|
+
<email>restapitest@gmail.com</email>
|
32
|
+
</author>
|
33
|
+
<gd:feedLink rel="http://schemas.google.com/acl/2007#accessControlList" href="http://docs.google.com/feeds/acl/private/full/document%3Adhmn2mkk_0d4rbv8d8"/>
|
34
|
+
</entry>
|
35
|
+
</feed>
|
36
|
+
|