gdocs_features 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/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
|
+
|