subjoin 0.2.1

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.
@@ -0,0 +1,89 @@
1
+ require "spec_helper"
2
+
3
+ module Subjoin
4
+ class ExampleResource < Resource
5
+ include Inheritable
6
+ ROOT_URI="http://example.com"
7
+ end
8
+
9
+ class NonStandardUri < ExampleResource
10
+ TYPE_PATH="nonstandard"
11
+ end
12
+
13
+ class Articles < ExampleResource
14
+ #TYPE_PATH="articles"
15
+ end
16
+
17
+ class ExamplePerson < ExampleResource
18
+ TYPE_PATH="people"
19
+ end
20
+
21
+ end
22
+
23
+ describe Subjoin::Inheritable do
24
+ before :each do
25
+ allow_any_instance_of(Faraday::Connection).
26
+ to receive(:get).and_return(double(Faraday::Response, :body => ARTICLE))
27
+ end
28
+
29
+ it "has a root uri" do
30
+ expect(Subjoin::ExampleResource::ROOT_URI).to eq "http://example.com"
31
+ end
32
+
33
+ describe "#type_url" do
34
+ it "is a class method" do
35
+ expect(Subjoin::ExampleResource::type_url).to eq URI("http://example.com/exampleresource")
36
+ end
37
+ end
38
+ end
39
+
40
+ describe Subjoin::Document do
41
+ describe "#new" do
42
+ context "with a single string parameter" do
43
+ it "maps derived types" do
44
+ expect_any_instance_of(Faraday::Connection)
45
+ .to receive(:get).with(URI("http://example.com/articles"), {}, Hash)
46
+ .and_return(double(Faraday::Response, :body => ARTICLE))
47
+ Subjoin::Document.new("articles")
48
+ end
49
+
50
+ it "returns objects of the right class" do
51
+ expect_any_instance_of(Faraday::Connection).
52
+ to receive(:get).
53
+ and_return(double(Faraday::Response, :body => COMPOUND))
54
+
55
+ expect(Subjoin::Document.new("articles").data.first).
56
+ to be_an_instance_of Subjoin::Articles
57
+ end
58
+
59
+ it "returns included objects of the right class" do
60
+ expect_any_instance_of(Faraday::Connection).
61
+ to receive(:get).
62
+ and_return(double(Faraday::Response, :body => COMPOUND))
63
+ expect(Subjoin::Document.new("articles").data.first.
64
+ rels["author"].first).
65
+ to be_an_instance_of Subjoin::ExamplePerson
66
+ end
67
+
68
+ it "returns Resource objects when there is no mapped type" do
69
+ expect_any_instance_of(Faraday::Connection).
70
+ to receive(:get).
71
+ and_return(double(Faraday::Response, :body => COMPOUND))
72
+ expect(Subjoin::Document.new("articles").data.first.
73
+ rels["comments"].first).
74
+ to be_an_instance_of Subjoin::Resource
75
+ end
76
+ end
77
+
78
+ context "with two string parameters" do
79
+ it "maps derived types with the second string as an id" do
80
+ expect_any_instance_of(Faraday::Connection)
81
+ .to receive(:get).with(URI("http://example.com/articles/2"), {}, Hash)
82
+ .and_return(double(Faraday::Response, :body => ARTICLE))
83
+ Subjoin::Document.new("articles", "2")
84
+ end
85
+ end
86
+ end
87
+ end
88
+
89
+
data/spec/link_spec.rb ADDED
@@ -0,0 +1,60 @@
1
+ require "spec_helper"
2
+
3
+ describe Subjoin::Link do
4
+ context "initialization with a string" do
5
+ before :each do
6
+ @link = Subjoin::Link.new(JSON.parse(LINKS)["self"])
7
+ end
8
+
9
+ it "should have an href attribute" do
10
+ expect(@link.href.to_s).to eq "http://example.com/posts"
11
+ end
12
+
13
+ it "should have a nil meta attribute" do
14
+ expect(@link.meta).to be_nil
15
+ end
16
+ end
17
+
18
+ context "initialization with an object" do
19
+ before :each do
20
+ @link = Subjoin::Link.new(JSON.parse(LINKS)["related"])
21
+ end
22
+
23
+ it "should have an href attribute" do
24
+ expect(@link.href.to_s).to eq "http://example.com/articles/1/comments"
25
+ end
26
+
27
+ context "when there is a meta attribute" do
28
+ it "should have a meta attribute" do
29
+ expect(@link.meta).to be_an_instance_of Subjoin::Meta
30
+ end
31
+ end
32
+
33
+ context "when there is no meta attribute" do
34
+ it "should not have a meta attribute" do
35
+ metaless = JSON.parse(LINKS)["related"]
36
+ metaless.delete("meta")
37
+ expect(Subjoin::Link.new(metaless).meta).to be_nil
38
+ end
39
+ end
40
+ end
41
+
42
+ describe "#has_meta?" do
43
+ it "should be false if there is no meta attribute" do
44
+ expect(Subjoin::Link.new(JSON.parse(LINKS)["self"]).has_meta?).
45
+ to eq false
46
+ end
47
+
48
+ it "should be true if there is a meta attribute" do
49
+ expect(Subjoin::Link.new(JSON.parse(LINKS)["related"]).has_meta?).
50
+ to eq true
51
+ end
52
+ end
53
+
54
+ describe "#to_s" do
55
+ it "should return the href" do
56
+ @l = Subjoin::Link.new(JSON.parse(LINKS)["self"])
57
+ expect("#{@l}").to eq "http://example.com/posts"
58
+ end
59
+ end
60
+ end
data/spec/meta_spec.rb ADDED
@@ -0,0 +1,11 @@
1
+ require "spec_helper"
2
+
3
+ describe "Subjoin::Meta" do
4
+ before :each do
5
+ @m = Subjoin::Meta.new(JSON.parse(META)['meta'])
6
+ end
7
+
8
+ it "has dynamic attributes" do
9
+ expect(@m["copyright"]).to eq "Copyright 2015 Example Corp."
10
+ end
11
+ end
@@ -0,0 +1,64 @@
1
+ require "spec_helper"
2
+
3
+
4
+ describe Subjoin::Relationship do
5
+ before :all do
6
+ @doc = Subjoin::Document.new(JSON.parse(COMPOUND))
7
+ @auths = @doc.data.first.relationships["author"]
8
+ end
9
+
10
+ it "is linkable" do
11
+ expect(@auths.links.map{|k,v| v.class}.uniq).to eq [Subjoin::Link]
12
+ end
13
+
14
+ it "has the right links" do
15
+ expect(@auths.links.keys).to eq ["self", "related"]
16
+ end
17
+
18
+ it "has a meta object" do
19
+ expect(@auths.meta).to be_an_instance_of Subjoin::Meta
20
+ end
21
+
22
+ describe "#lookup" do
23
+ it "returns an Array of resources" do
24
+ expect(@auths.lookup.map{|o| o.class}.uniq).to eq [Subjoin::Resource]
25
+ end
26
+ end
27
+
28
+ describe "#linkages" do
29
+ context "with a single linkage" do
30
+ it "returns an Array" do
31
+ expect(@auths.linkages).to be_an_instance_of Array
32
+ end
33
+
34
+ it "returns an array with a single member" do
35
+ expect(@auths.linkages.count).to eq 1
36
+ end
37
+
38
+ it "returns an array of Identifier objects" do
39
+ expect(@auths.linkages.map{|l| l.class}.uniq).to eq [Subjoin::Identifier]
40
+ end
41
+ end
42
+
43
+ context "with an array of linkages" do
44
+ before :each do
45
+ @comments = Subjoin::Relationship.new(
46
+ JSON.parse(ARTICLE)['data']['relationships']['comments'],
47
+ nil
48
+ )
49
+ end
50
+
51
+ it "returns an Array" do
52
+ expect(@comments.linkages).to be_an_instance_of Array
53
+ end
54
+
55
+ it "returns an array with more than 1 member" do
56
+ expect(@comments.linkages.count).to be > 1
57
+ end
58
+
59
+ it "returns an array of Identifier objects" do
60
+ expect(@comments.linkages.map{|l| l.class}.uniq).to eq [Subjoin::Identifier]
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,139 @@
1
+ require "spec_helper"
2
+
3
+ class Base < Subjoin::Resource
4
+ def self.root
5
+ "http://example.com"
6
+ end
7
+ end
8
+
9
+ class Article < Base
10
+ end
11
+
12
+ describe Subjoin::Resource do
13
+ before :each do
14
+ allow_any_instance_of(Faraday::Connection).
15
+ to receive(:get).and_return(double(Faraday::Response, :body => ARTICLE))
16
+ end
17
+
18
+ context "using instance methods to retrieve single resources" do
19
+ describe "#initialize" do
20
+ context "passing a URI as a parameter" do
21
+ it "should get the same a parameter" do
22
+ expect_any_instance_of(Faraday::Connection)
23
+ .to receive(:get).
24
+ with(URI("http://example.com/articles/2"), {}, Hash).
25
+ and_return(double(Faraday::Response, :body => ARTICLE))
26
+
27
+ @articles = Subjoin::Resource.
28
+ new(URI("http://example.com/articles/2"))
29
+
30
+ end
31
+
32
+ it "should raise an error if the response is not a single object" do
33
+ expect_any_instance_of(Faraday::Connection)
34
+ .to receive(:get)
35
+ .and_return(double(Faraday::Response, :body => COMPOUND))
36
+ expect { Subjoin::Resource.
37
+ new(URI("http://example.com/articles")) }
38
+ .to raise_error(Subjoin::UnexpectedTypeError)
39
+ end
40
+ end
41
+
42
+ context "passing a hash as a parameter" do
43
+ it "should succeed" do
44
+ expect(Subjoin::Resource.new(JSON.parse(ARTICLE)).id).to eq "1"
45
+ end
46
+ end
47
+ end
48
+ end
49
+
50
+ describe "simple methods" do
51
+ before :each do
52
+ @article = Subjoin::Resource.new(URI("http://example.com/articles/1"))
53
+ end
54
+
55
+ it "should have an id" do
56
+ expect(@article.id).to eq "1"
57
+ end
58
+
59
+ it "should have a type" do
60
+ expect(@article.type).to eq "articles"
61
+ end
62
+
63
+ it "should have automatic attributes" do
64
+ expect(@article["title"]).to eq "JSON API paints my bikeshed!"
65
+ end
66
+ end
67
+
68
+ describe "#links" do
69
+ before :each do
70
+ @article = Subjoin::Resource.new(URI("http://example.com/articles/1"))
71
+ end
72
+
73
+ context "with no parameter" do
74
+ it "returns a Hash of all the links" do
75
+ expect(@article.links.map{|k,v| v.class}.uniq).to eq [Subjoin::Link]
76
+ end
77
+ end
78
+
79
+ context "with a parameter" do
80
+ it "returns a link object" do
81
+ expect(@article.links["self"]).to be_an_instance_of Subjoin::Link
82
+ end
83
+ end
84
+ end
85
+
86
+ describe "#rels" do
87
+ context "when there are included resources" do
88
+ before :each do
89
+ allow_any_instance_of(Faraday::Connection).
90
+ to receive(:get).
91
+ and_return(double(Faraday::Response, :body => COMPOUND))
92
+ @article = Subjoin::Document.new(URI("http://example.com/articles/1")).
93
+ data.first
94
+ end
95
+
96
+ context "called with no parameters" do
97
+ it "returns a Hash of Arrays of Relationship objects" do
98
+ expect(@article.rels.map{|k, r| r}.flatten.map{|r| r.class}.uniq).
99
+ to eq [Subjoin::Resource]
100
+ end
101
+ end
102
+
103
+ context "called with a spec parameter" do
104
+ it "returns an array" do
105
+ expect(@article.rels("author").map{|r| r.class}).
106
+ to eq [Subjoin::Resource]
107
+ end
108
+ end
109
+ end
110
+
111
+ context "when there are no included resources" do
112
+ before :each do
113
+ @article = Subjoin::Resource.new(URI("http://example.com/articles/1"))
114
+ end
115
+
116
+ context "called with no spec parameter" do
117
+ it "returns nil" do
118
+ expect(@article.rels).to be_nil
119
+ end
120
+ end
121
+
122
+ context "called with a spec parameter" do
123
+ it "returns nil" do
124
+ expect(@article.rels("author")).to be_nil
125
+ end
126
+ end
127
+ end
128
+ end
129
+
130
+ describe "#meta" do
131
+ before :each do
132
+ @article = Subjoin::Resource.new(URI("http://example.com/articles/1"))
133
+ end
134
+
135
+ it "returns a Meta object" do
136
+ expect(@article.meta).to be_an_instance_of Subjoin::Meta
137
+ end
138
+ end
139
+ end
@@ -0,0 +1,8 @@
1
+ {
2
+ "errors": [
3
+ {
4
+ "title": "Resource Not Found",
5
+ "status": 404
6
+ }
7
+ ]
8
+ }
@@ -0,0 +1,37 @@
1
+ {
2
+ "data": {
3
+ "type": "articles",
4
+ "id": "1",
5
+ "attributes": {
6
+ "title": "JSON API paints my bikeshed!"
7
+ },
8
+ "links": {
9
+ "self": "http://example.com/articles/1"
10
+ },
11
+ "relationships": {
12
+ "author": {
13
+ "links": {
14
+ "self": "http://example.com/articles/1/relationships/author",
15
+ "related": "http://example.com/articles/1/author"
16
+ },
17
+ "data": { "type": "people", "id": "9" },
18
+ "meta": {
19
+ "explanation": "Who wrote the article"
20
+ }
21
+ },
22
+ "comments": {
23
+ "links": {
24
+ "self": "http://example.com/articles/1/relationships/comments",
25
+ "related": "http://example.com/articles/1/comments"
26
+ },
27
+ "data": [
28
+ { "type": "comments", "id": "5" },
29
+ { "type": "comments", "id": "12" }
30
+ ]
31
+ }
32
+ },
33
+ "meta": {
34
+ "reason": "To have an example meta object"
35
+ }
36
+ }
37
+ }
@@ -0,0 +1,73 @@
1
+ {
2
+ "data": [{
3
+ "type": "articles",
4
+ "id": "1",
5
+ "attributes": {
6
+ "title": "JSON API paints my bikeshed!"
7
+ },
8
+ "links": {
9
+ "self": "http://example.com/articles/1"
10
+ },
11
+ "relationships": {
12
+ "author": {
13
+ "links": {
14
+ "self": "http://example.com/articles/1/relationships/author",
15
+ "related": "http://example.com/articles/1/author"
16
+ },
17
+ "data": { "type": "people", "id": "9" },
18
+ "meta": {
19
+ "explanation": "Who wrote the article"
20
+ }
21
+ },
22
+ "comments": {
23
+ "links": {
24
+ "self": "http://example.com/articles/1/relationships/comments",
25
+ "related": "http://example.com/articles/1/comments"
26
+ },
27
+ "data": [
28
+ { "type": "comments", "id": "5" },
29
+ { "type": "comments", "id": "12" }
30
+ ]
31
+ }
32
+ }
33
+ }],
34
+ "included": [{
35
+ "type": "people",
36
+ "id": "9",
37
+ "attributes": {
38
+ "first-name": "Dan",
39
+ "last-name": "Gebhardt",
40
+ "twitter": "dgeb"
41
+ },
42
+ "links": {
43
+ "self": "http://example.com/people/9"
44
+ }
45
+ }, {
46
+ "type": "comments",
47
+ "id": "5",
48
+ "attributes": {
49
+ "body": "First!"
50
+ },
51
+ "links": {
52
+ "self": "http://example.com/comments/5"
53
+ }
54
+ }, {
55
+ "type": "comments",
56
+ "id": "12",
57
+ "attributes": {
58
+ "body": "I like XML better"
59
+ },
60
+ "links": {
61
+ "self": "http://example.com/comments/12"
62
+ }
63
+ }],
64
+ "links": {
65
+ "related": "http://jsonapi.org"
66
+ },
67
+ "meta": {
68
+ "category": "Example response"
69
+ },
70
+ "jsonapi": {
71
+ "version": "1.0"
72
+ }
73
+ }