wayback 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.
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