wayback 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. data/.yardopts +10 -0
  2. data/CHANGELOG.md +3 -0
  3. data/CONTRIBUTING.md +52 -0
  4. data/LICENSE.md +20 -0
  5. data/README.md +81 -0
  6. data/Rakefile +11 -0
  7. data/lib/wayback.rb +32 -0
  8. data/lib/wayback/api/archive.rb +42 -0
  9. data/lib/wayback/api/utils.rb +27 -0
  10. data/lib/wayback/archive.rb +15 -0
  11. data/lib/wayback/base.rb +127 -0
  12. data/lib/wayback/client.rb +62 -0
  13. data/lib/wayback/configurable.rb +48 -0
  14. data/lib/wayback/default.rb +68 -0
  15. data/lib/wayback/error.rb +31 -0
  16. data/lib/wayback/error/already_favorited.rb +10 -0
  17. data/lib/wayback/error/already_retweeted.rb +10 -0
  18. data/lib/wayback/error/bad_gateway.rb +11 -0
  19. data/lib/wayback/error/bad_request.rb +10 -0
  20. data/lib/wayback/error/client_error.rb +28 -0
  21. data/lib/wayback/error/configuration_error.rb +8 -0
  22. data/lib/wayback/error/decode_error.rb +9 -0
  23. data/lib/wayback/error/forbidden.rb +10 -0
  24. data/lib/wayback/error/gateway_timeout.rb +11 -0
  25. data/lib/wayback/error/identity_map_key_error.rb +9 -0
  26. data/lib/wayback/error/internal_server_error.rb +11 -0
  27. data/lib/wayback/error/not_acceptable.rb +10 -0
  28. data/lib/wayback/error/not_found.rb +10 -0
  29. data/lib/wayback/error/server_error.rb +28 -0
  30. data/lib/wayback/error/service_unavailable.rb +11 -0
  31. data/lib/wayback/error/too_many_requests.rb +12 -0
  32. data/lib/wayback/error/unauthorized.rb +10 -0
  33. data/lib/wayback/error/unprocessable_entity.rb +10 -0
  34. data/lib/wayback/factory.rb +21 -0
  35. data/lib/wayback/identity.rb +50 -0
  36. data/lib/wayback/identity_map.rb +22 -0
  37. data/lib/wayback/page.rb +18 -0
  38. data/lib/wayback/response/parse_memento.rb +61 -0
  39. data/lib/wayback/response/parse_memento_page.rb +23 -0
  40. data/lib/wayback/response/raise_error.rb +31 -0
  41. data/lib/wayback/version.rb +18 -0
  42. data/spec/fixtures/list.timemap +9 -0
  43. data/spec/fixtures/page.html +225 -0
  44. data/spec/helper.rb +65 -0
  45. data/spec/wayback/api/archive_spec.rb +73 -0
  46. data/spec/wayback/archive_spec.rb +23 -0
  47. data/spec/wayback/base_spec.rb +117 -0
  48. data/spec/wayback/client_spec.rb +114 -0
  49. data/spec/wayback/error/client_error_spec.rb +23 -0
  50. data/spec/wayback/error/server_error_spec.rb +20 -0
  51. data/spec/wayback/error_spec.rb +20 -0
  52. data/spec/wayback/identifiable_spec.rb +50 -0
  53. data/spec/wayback/page_spec.rb +36 -0
  54. data/spec/wayback_spec.rb +47 -0
  55. data/wayback.gemspec +26 -0
  56. metadata +175 -0
@@ -0,0 +1,73 @@
1
+ require 'helper'
2
+
3
+ describe Wayback::API::Archive do
4
+
5
+ before do
6
+ @client = Wayback::Client.new
7
+ end
8
+
9
+ # N.B. IN SPEC, NOT USING http:// DUE TO PARSING ISSUE WITH DOUBLE BACKSLASH.
10
+
11
+ describe "#list" do
12
+ before do
13
+ stub_get("/list/timemap/link/gleu.ch").to_return(:body => fixture("list.timemap"), :headers => {:content_type => "application/link-format"})
14
+ end
15
+ it "requests the correct resource" do
16
+ @client.list('gleu.ch')
17
+ expect(a_get("/list/timemap/link/gleu.ch")).to have_been_made
18
+ end
19
+ it "returns the link data" do
20
+ timemap = @client.list('gleu.ch')
21
+ expect(timemap).to be_a Wayback::Archive
22
+ expect(timemap.id).to eq ('http://gleu.ch')
23
+ expect(timemap.first_date).to eq (1303064571)
24
+ expect(timemap.first_date?).to be_true
25
+ end
26
+ end
27
+
28
+ describe "#page" do
29
+ before do
30
+ stub_get("/memento/20130129170322/gleu.ch").to_return(:body => fixture("page.html"), :headers => {:content_type => "text/html"})
31
+ end
32
+ it "requests the correct resource" do
33
+ @client.page('gleu.ch', 20130129170322)
34
+ expect(a_get("/memento/20130129170322/gleu.ch")).to have_been_made
35
+ end
36
+ it "returns the desired page on date" do
37
+ page = @client.page('gleu.ch', 20130129170322)
38
+ expect(page).to be_a Wayback::Page
39
+ expect(page.html).to match /^\<\!DOCTYPE html\>.*http\:\/\/gleu\.ch.*\<\/html\>/im
40
+ end
41
+ it "returns the first desired page" do
42
+ stub_get("/memento/0/gleu.ch").to_return(:body => fixture("page.html"), :headers => {:content_type => "text/html"})
43
+ page = @client.page('gleu.ch', :first)
44
+ expect(page).to be_a Wayback::Page
45
+ expect(page.html).to match /^\<\!DOCTYPE html\>.*http\:\/\/gleu\.ch.*\<\/html\>/im
46
+ end
47
+ it "returns the last desired page" do
48
+ stub_get("/memento/#{Time.now.to_i}/gleu.ch").to_return(:body => fixture("page.html"), :headers => {:content_type => "text/html"})
49
+ page = @client.page('gleu.ch', :last)
50
+ expect(page).to be_a Wayback::Page
51
+ expect(page.html).to match(/^\<\!DOCTYPE html\>.*http\:\/\/gleu\.ch.*\<\/html\>/im)
52
+ end
53
+ it "returns the desired page for Time" do
54
+ stub_get("/memento/#{Time.now.to_i}/gleu.ch").to_return(:body => fixture("page.html"), :headers => {:content_type => "text/html"})
55
+ page = @client.page('gleu.ch', Time.now)
56
+ expect(page).to be_a Wayback::Page
57
+ expect(page.html).to match(/^\<\!DOCTYPE html\>.*http\:\/\/gleu\.ch.*\<\/html\>/im)
58
+ end
59
+ it "returns the desired page for Time string" do
60
+ stub_get("/memento/#{Time.now.to_i}/gleu.ch").to_return(:body => fixture("page.html"), :headers => {:content_type => "text/html"})
61
+ page = @client.page('gleu.ch', Time.now.to_s)
62
+ expect(page).to be_a Wayback::Page
63
+ expect(page.html).to match(/^\<\!DOCTYPE html\>.*http\:\/\/gleu\.ch.*\<\/html\>/im)
64
+ end
65
+ # it "handles when error exists" do
66
+ # stub_get("/memento/#{Time.now.to_i}/gleu.ch").to_return(:status => 204, :body => '', :headers => {:content_type => "text/xml"})
67
+ # page = @client.page('gleu.ch', Time.now.to_s)
68
+ # expect(page).to be_a Wayback::Page
69
+ # expect(page.html).to match(/^\<\!DOCTYPE html\>.*http\:\/\/gleu\.ch.*\<\/html\>/im)
70
+ # end
71
+ end
72
+
73
+ end
@@ -0,0 +1,23 @@
1
+ require 'helper'
2
+
3
+ describe Wayback::Archive do
4
+
5
+ describe "#==" do
6
+ it "returns true when objects IDs are the same" do
7
+ saved_search = Wayback::Archive.new(:id => 1, :name => "foo")
8
+ other = Wayback::Archive.new(:id => 1, :name => "bar")
9
+ expect(saved_search == other).to be_true
10
+ end
11
+ it "returns false when objects IDs are different" do
12
+ saved_search = Wayback::Archive.new(:id => 1)
13
+ other = Wayback::Archive.new(:id => 2)
14
+ expect(saved_search == other).to be_false
15
+ end
16
+ it "returns false when classes are different" do
17
+ saved_search = Wayback::Archive.new(:id => 1)
18
+ other = Wayback::Identity.new(:id => 1)
19
+ expect(saved_search == other).to be_false
20
+ end
21
+ end
22
+
23
+ end
@@ -0,0 +1,117 @@
1
+ require 'helper'
2
+
3
+ describe Wayback::Base do
4
+
5
+ context "identity map enabled" do
6
+ before do
7
+ Wayback.identity_map = Wayback::IdentityMap
8
+ object = Wayback::Base.new(:id => 1)
9
+ @base = Wayback::Base.store(object)
10
+ end
11
+
12
+ after do
13
+ Wayback.identity_map = false
14
+ end
15
+
16
+ describe ".identity_map" do
17
+ it "returns an instance of the identity map" do
18
+ expect(Wayback::Base.identity_map).to be_a Wayback::IdentityMap
19
+ end
20
+ end
21
+
22
+ describe ".fetch" do
23
+ it "returns existing objects" do
24
+ expect(Wayback::Base.fetch(:id => 1)).to be
25
+ end
26
+
27
+ it "raises an error on objects that don't exist" do
28
+ expect{Wayback::Base.fetch(:id => 6)}.to raise_error Wayback::Error::IdentityMapKeyError
29
+ end
30
+ end
31
+
32
+ describe ".store" do
33
+ it "stores Wayback::Base objects" do
34
+ object = Wayback::Base.new(:id => 4)
35
+ expect(Wayback::Base.store(object)).to be_a Wayback::Base
36
+ end
37
+ end
38
+
39
+ describe ".fetch_or_new" do
40
+ it "returns existing objects" do
41
+ expect(Wayback::Base.fetch_or_new(:id => 1)).to be
42
+ end
43
+ it "creates new objects and stores them" do
44
+ expect(Wayback::Base.fetch_or_new(:id => 2)).to be
45
+ expect(Wayback::Base.fetch(:id => 2)).to be
46
+ end
47
+ end
48
+
49
+ describe "#[]" do
50
+ it "calls methods using [] with symbol" do
51
+ expect(@base[:object_id]).to be_an Integer
52
+ end
53
+ it "calls methods using [] with string" do
54
+ expect(@base['object_id']).to be_an Integer
55
+ end
56
+ it "returns nil for missing method" do
57
+ expect(@base[:foo]).to be_nil
58
+ expect(@base['foo']).to be_nil
59
+ end
60
+ end
61
+
62
+ describe "#to_hash" do
63
+ it "returns a hash" do
64
+ expect(@base.to_hash).to be_a Hash
65
+ expect(@base.to_hash[:id]).to eq 1
66
+ end
67
+ end
68
+
69
+ describe "identical objects" do
70
+ it "have the same object_id" do
71
+ expect(@base.object_id).to eq Wayback::Base.fetch(:id => 1).object_id
72
+ end
73
+ end
74
+
75
+ end
76
+
77
+ context "identity map disabled" do
78
+ before(:all) do
79
+ Wayback.identity_map = false
80
+ end
81
+ after(:all) do
82
+ Wayback.identity_map = Wayback::IdentityMap
83
+ end
84
+
85
+ describe ".identity_map" do
86
+ it "returns nil" do
87
+ expect(Wayback::Base.identity_map).to be_nil
88
+ end
89
+ end
90
+
91
+ describe ".fetch" do
92
+ it "returns nil" do
93
+ expect(Wayback::Base.fetch(:id => 1)).to be_nil
94
+ end
95
+ end
96
+
97
+ describe ".store" do
98
+ it "returns an instance of the object" do
99
+ expect(Wayback::Base.store(Wayback::Base.new(:id => 1))).to be_a Wayback::Base
100
+ end
101
+ end
102
+
103
+ describe ".fetch_or_new" do
104
+ it "creates new objects" do
105
+ expect(Wayback::Base.fetch_or_new(:id => 2)).to be
106
+ expect(Wayback.identity_map).to be_false
107
+ end
108
+ end
109
+ end
110
+
111
+ describe '#attrs' do
112
+ it 'returns a hash of attributes' do
113
+ expect(Wayback::Base.new(:id => 1).attrs).to eq({:id => 1})
114
+ end
115
+ end
116
+
117
+ end
@@ -0,0 +1,114 @@
1
+ require 'helper'
2
+
3
+ describe Wayback::Client do
4
+
5
+ subject do
6
+ Wayback::Client.new(:consumer_key => "CK", :consumer_secret => "CS", :oauth_token => "OT", :oauth_token_secret => "OS")
7
+ end
8
+
9
+ context "with module configuration" do
10
+
11
+ before do
12
+ Wayback.configure do |config|
13
+ Wayback::Configurable.keys.each do |key|
14
+ config.send("#{key}=", key)
15
+ end
16
+ end
17
+ end
18
+
19
+ after do
20
+ Wayback.reset!
21
+ end
22
+
23
+ it "inherits the module configuration" do
24
+ client = Wayback::Client.new
25
+ Wayback::Configurable.keys.each do |key|
26
+ expect(client.instance_variable_get(:"@#{key}")).to eq key
27
+ end
28
+ end
29
+
30
+ context "with class configuration" do
31
+
32
+ before do
33
+ @configuration = {
34
+ :connection_options => {:timeout => 10},
35
+ :endpoint => 'http://xolator.com/',
36
+ :middleware => Proc.new{},
37
+ :identity_map => ::Hash
38
+ }
39
+ end
40
+
41
+ context "during initialization" do
42
+ it "overrides the module configuration" do
43
+ client = Wayback::Client.new(@configuration)
44
+ Wayback::Configurable.keys.each do |key|
45
+ expect(client.instance_variable_get(:"@#{key}")).to eq @configuration[key]
46
+ end
47
+ end
48
+ end
49
+
50
+ context "after initialization" do
51
+ it "overrides the module configuration after initialization" do
52
+ client = Wayback::Client.new
53
+ client.configure do |config|
54
+ @configuration.each do |key, value|
55
+ config.send("#{key}=", value)
56
+ end
57
+ end
58
+ Wayback::Configurable.keys.each do |key|
59
+ expect(client.instance_variable_get(:"@#{key}")).to eq @configuration[key]
60
+ end
61
+ end
62
+ end
63
+
64
+ end
65
+ end
66
+
67
+ describe "#delete" do
68
+ before do
69
+ stub_delete("/custom/delete").with(:query => {:deleted => "object"})
70
+ end
71
+ it "allows custom delete requests" do
72
+ subject.delete("/custom/delete", {:deleted => "object"})
73
+ expect(a_delete("/custom/delete").with(:query => {:deleted => "object"})).to have_been_made
74
+ end
75
+ end
76
+
77
+ describe "#put" do
78
+ before do
79
+ stub_put("/custom/put").with(:body => {:updated => "object"})
80
+ end
81
+ it "allows custom put requests" do
82
+ subject.put("/custom/put", {:updated => "object"})
83
+ expect(a_put("/custom/put").with(:body => {:updated => "object"})).to have_been_made
84
+ end
85
+ end
86
+
87
+ describe "#post" do
88
+ before do
89
+ stub_post("/custom/post").with(:body => {:updated => "object"})
90
+ end
91
+ it "allows custom post requests" do
92
+ subject.post("/custom/post", {:updated => "object"})
93
+ expect(a_post("/custom/post").with(:body => {:updated => "object"})).to have_been_made
94
+ end
95
+ end
96
+
97
+ describe "#connection" do
98
+ it "looks like Faraday connection" do
99
+ expect(subject.send(:connection)).to respond_to(:run_request)
100
+ end
101
+ it "memoizes the connection" do
102
+ c1, c2 = subject.send(:connection), subject.send(:connection)
103
+ expect(c1.object_id).to eq c2.object_id
104
+ end
105
+ end
106
+
107
+ describe "#request" do
108
+ it "catches Faraday errors" do
109
+ subject.stub!(:connection).and_raise(Faraday::Error::ClientError.new("Oops"))
110
+ expect{subject.send(:request, :get, "/path")}.to raise_error Wayback::Error::ClientError
111
+ end
112
+ end
113
+
114
+ end
@@ -0,0 +1,23 @@
1
+ require 'helper'
2
+
3
+ describe Wayback::Error::ClientError do
4
+
5
+ before do
6
+ @client = Wayback::Client.new
7
+ end
8
+
9
+ Wayback::Error::ClientError.errors.each do |status, exception|
10
+ [nil, "error"].each do |body|
11
+ context "when HTTP status is #{status} and body is #{body.inspect}" do
12
+ before do
13
+ body_message = '<wayback><error><title>Hrm.</title><message>Wayback Machine doesn&apos;t have that page archived.</message></error></wayback>' unless body.nil?
14
+ stub_get("/list/timemap/link/gleu.ch").to_return(:body => body_message, :status => status)
15
+ end
16
+ it "raises #{exception.name}" do
17
+ expect{@client.list('gleu.ch')}.to raise_error exception
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ end
@@ -0,0 +1,20 @@
1
+ require 'helper'
2
+
3
+ describe Wayback::Error::ServerError do
4
+
5
+ before do
6
+ @client = Wayback::Client.new
7
+ end
8
+
9
+ Wayback::Error::ServerError.errors.each do |status, exception|
10
+ context "when HTTP status is #{status}" do
11
+ before do
12
+ stub_get("/list/timemap/link/gleu.ch").to_return(:status => status)
13
+ end
14
+ it "raises #{exception.name}" do
15
+ expect{@client.list('gleu.ch')}.to raise_error exception
16
+ end
17
+ end
18
+ end
19
+
20
+ end
@@ -0,0 +1,20 @@
1
+ require 'helper'
2
+
3
+ describe Wayback::Error do
4
+
5
+ describe "#initialize" do
6
+ it "wraps another error class" do
7
+ begin
8
+ raise Faraday::Error::ClientError.new("Oops")
9
+ rescue Faraday::Error::ClientError
10
+ begin
11
+ raise Wayback::Error
12
+ rescue Wayback::Error => error
13
+ expect(error.message).to eq "Oops"
14
+ expect(error.wrapped_exception.class).to eq Faraday::Error::ClientError
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+ end
@@ -0,0 +1,50 @@
1
+ require 'helper'
2
+
3
+ describe Wayback::Identity do
4
+
5
+ describe "#initialize" do
6
+ it "raises an ArgumentError when type is not specified" do
7
+ expect{Wayback::Identity.new}.to raise_error ArgumentError
8
+ end
9
+ end
10
+
11
+ context "identity map enabled" do
12
+ before do
13
+ Wayback.identity_map = Wayback::IdentityMap
14
+ end
15
+
16
+ after do
17
+ Wayback.identity_map = false
18
+ end
19
+
20
+ describe ".fetch" do
21
+ it "returns existing objects" do
22
+ Wayback::Identity.store(Wayback::Identity.new(:id => 1))
23
+ expect(Wayback::Identity.fetch(:id => 1)).to be
24
+ end
25
+
26
+ it "raises an error on objects that don't exist" do
27
+ expect{Wayback::Identity.fetch(:id => 6)}.to raise_error Wayback::Error::IdentityMapKeyError
28
+ end
29
+ end
30
+ end
31
+
32
+ describe "#==" do
33
+ it "returns true when objects IDs are the same" do
34
+ one = Wayback::Identity.new(:id => 1, :screen_name => "gleuch")
35
+ two = Wayback::Identity.new(:id => 1, :screen_name => "ohjia")
36
+ expect(one == two).to be_true
37
+ end
38
+ it "returns false when objects IDs are different" do
39
+ one = Wayback::Identity.new(:id => 1)
40
+ two = Wayback::Identity.new(:id => 2)
41
+ expect(one == two).to be_false
42
+ end
43
+ it "returns false when classes are different" do
44
+ one = Wayback::Identity.new(:id => 1)
45
+ two = Wayback::Base.new(:id => 1)
46
+ expect(one == two).to be_false
47
+ end
48
+ end
49
+
50
+ end