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.
- data/.yardopts +10 -0
- data/CHANGELOG.md +3 -0
- data/CONTRIBUTING.md +52 -0
- data/LICENSE.md +20 -0
- data/README.md +81 -0
- data/Rakefile +11 -0
- data/lib/wayback.rb +32 -0
- data/lib/wayback/api/archive.rb +42 -0
- data/lib/wayback/api/utils.rb +27 -0
- data/lib/wayback/archive.rb +15 -0
- data/lib/wayback/base.rb +127 -0
- data/lib/wayback/client.rb +62 -0
- data/lib/wayback/configurable.rb +48 -0
- data/lib/wayback/default.rb +68 -0
- data/lib/wayback/error.rb +31 -0
- data/lib/wayback/error/already_favorited.rb +10 -0
- data/lib/wayback/error/already_retweeted.rb +10 -0
- data/lib/wayback/error/bad_gateway.rb +11 -0
- data/lib/wayback/error/bad_request.rb +10 -0
- data/lib/wayback/error/client_error.rb +28 -0
- data/lib/wayback/error/configuration_error.rb +8 -0
- data/lib/wayback/error/decode_error.rb +9 -0
- data/lib/wayback/error/forbidden.rb +10 -0
- data/lib/wayback/error/gateway_timeout.rb +11 -0
- data/lib/wayback/error/identity_map_key_error.rb +9 -0
- data/lib/wayback/error/internal_server_error.rb +11 -0
- data/lib/wayback/error/not_acceptable.rb +10 -0
- data/lib/wayback/error/not_found.rb +10 -0
- data/lib/wayback/error/server_error.rb +28 -0
- data/lib/wayback/error/service_unavailable.rb +11 -0
- data/lib/wayback/error/too_many_requests.rb +12 -0
- data/lib/wayback/error/unauthorized.rb +10 -0
- data/lib/wayback/error/unprocessable_entity.rb +10 -0
- data/lib/wayback/factory.rb +21 -0
- data/lib/wayback/identity.rb +50 -0
- data/lib/wayback/identity_map.rb +22 -0
- data/lib/wayback/page.rb +18 -0
- data/lib/wayback/response/parse_memento.rb +61 -0
- data/lib/wayback/response/parse_memento_page.rb +23 -0
- data/lib/wayback/response/raise_error.rb +31 -0
- data/lib/wayback/version.rb +18 -0
- data/spec/fixtures/list.timemap +9 -0
- data/spec/fixtures/page.html +225 -0
- data/spec/helper.rb +65 -0
- data/spec/wayback/api/archive_spec.rb +73 -0
- data/spec/wayback/archive_spec.rb +23 -0
- data/spec/wayback/base_spec.rb +117 -0
- data/spec/wayback/client_spec.rb +114 -0
- data/spec/wayback/error/client_error_spec.rb +23 -0
- data/spec/wayback/error/server_error_spec.rb +20 -0
- data/spec/wayback/error_spec.rb +20 -0
- data/spec/wayback/identifiable_spec.rb +50 -0
- data/spec/wayback/page_spec.rb +36 -0
- data/spec/wayback_spec.rb +47 -0
- data/wayback.gemspec +26 -0
- 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'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
|