envato 0.0.0 → 1.0.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 (62) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +46 -0
  3. data/.rspec +5 -0
  4. data/.rubocop.yml +142 -0
  5. data/Gemfile +5 -0
  6. data/Gemfile.lock +84 -0
  7. data/LICENSE +7 -0
  8. data/README.md +152 -0
  9. data/Rakefile +16 -0
  10. data/envato.gemspec +34 -0
  11. data/lib/envato/client.rb +55 -0
  12. data/lib/envato/collection.rb +25 -0
  13. data/lib/envato/error.rb +6 -0
  14. data/lib/envato/object.rb +25 -0
  15. data/lib/envato/objects/types.rb +19 -0
  16. data/lib/envato/resource.rb +59 -0
  17. data/lib/envato/resources/bookmarks.rb +34 -0
  18. data/lib/envato/resources/item.rb +43 -0
  19. data/lib/envato/resources/market.rb +131 -0
  20. data/lib/envato/resources/markets.rb +42 -0
  21. data/lib/envato/resources/search.rb +21 -0
  22. data/lib/envato/resources/user.rb +60 -0
  23. data/lib/envato/resources/users.rb +10 -0
  24. data/lib/envato/version.rb +8 -0
  25. data/lib/envato.rb +39 -0
  26. data/spec/bookmarks_spec.rb +15 -0
  27. data/spec/envato_spec.rb +26 -0
  28. data/spec/item_spec.rb +90 -0
  29. data/spec/market_spec.rb +100 -0
  30. data/spec/markets_spec.rb +14 -0
  31. data/spec/search_spec.rb +41 -0
  32. data/spec/spec_helper.rb +51 -0
  33. data/spec/user_spec.rb +118 -0
  34. data/spec/users_spec.rb +15 -0
  35. data/spec/vcr/bookmarks_list.yml +87 -0
  36. data/spec/vcr/item_info.yml +88 -0
  37. data/spec/vcr/item_list_purchases.yml +87 -0
  38. data/spec/vcr/item_prices.yml +86 -0
  39. data/spec/vcr/item_purchases.yml +87 -0
  40. data/spec/vcr/item_version.yml +87 -0
  41. data/spec/vcr/market_categories_graphicriver.yml +147 -0
  42. data/spec/vcr/market_categories_themeforest.yml +201 -0
  43. data/spec/vcr/market_features_graphicriver.yml +97 -0
  44. data/spec/vcr/market_features_themeforest.yml +93 -0
  45. data/spec/vcr/market_new_files.yml +86 -0
  46. data/spec/vcr/market_new_files_graphicriver_graphics.yml +115 -0
  47. data/spec/vcr/market_popular_items_themeforest.yml +86 -0
  48. data/spec/vcr/market_total_items.yml +85 -0
  49. data/spec/vcr/search_comments.yml +88 -0
  50. data/spec/vcr/search_item.yml +88 -0
  51. data/spec/vcr/search_more_like_this.yml +88 -0
  52. data/spec/vcr/user_account.yml +86 -0
  53. data/spec/vcr/user_badges.yml +98 -0
  54. data/spec/vcr/user_badges_not_exists.yml +83 -0
  55. data/spec/vcr/user_collection.yml +88 -0
  56. data/spec/vcr/user_collections.yml +90 -0
  57. data/spec/vcr/user_email.yml +85 -0
  58. data/spec/vcr/user_items.yml +86 -0
  59. data/spec/vcr/user_name.yml +85 -0
  60. data/spec/vcr/user_statement.yml +111 -0
  61. data/spec/vcr/users_total.yml +85 -0
  62. metadata +147 -3
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Envato
4
+ class Resource
5
+ attr_reader :client
6
+
7
+ def initialize(client)
8
+ @client = client
9
+ end
10
+
11
+ private
12
+
13
+ def get(url, params: {}, headers: {})
14
+ handle_response client.connection.get(url, params, headers)
15
+ end
16
+
17
+ def post(url, body:, headers: {})
18
+ handle_response client.connection.post(url, body, headers)
19
+ end
20
+
21
+ def patch(url, body:, headers: {})
22
+ handle_response client.connection.patch(url, body, headers)
23
+ end
24
+
25
+ def put(url, body:, headers: {})
26
+ handle_response client.connection.put(url, body, headers)
27
+ end
28
+
29
+ def delete(url, params: {}, headers: {})
30
+ handle_response client.connection.delete(url, params, headers)
31
+ end
32
+ alias delete_request delete
33
+
34
+ # rubocop:disable Metrics/CyclomaticComplexity
35
+ # rubocop:disable Metrics/AbcSize
36
+ def handle_response(response)
37
+ case response.status
38
+ when 400
39
+ raise Error, "Your request was malformed. #{response.body['error']}"
40
+ when 401
41
+ raise Error, "You did not supply valid authentication credentials. #{response.body['error']}"
42
+ when 403
43
+ raise Error, "You are not allowed to perform that action. #{response.body['error']}"
44
+ when 404
45
+ raise Error, "No results were found for your request. #{response.body['error']}"
46
+ when 429
47
+ raise Error, "Your request exceeded the API rate limit. #{response.body['error']}"
48
+ when 500
49
+ raise Error, "We were unable to perform the request due to server-side problems. #{response.body['error']}"
50
+ when 503
51
+ raise Error, "You have been rate limited for sending more requests per second. #{response.body['error']}"
52
+ end
53
+
54
+ response
55
+ end
56
+ # rubocop:enable Metrics/AbcSize
57
+ # rubocop:enable Metrics/CyclomaticComplexity
58
+ end
59
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Envato
4
+ class BookmarksResource < Resource
5
+ def list
6
+ resp = get("v3/market/user/bookmarks")
7
+ Collection.from_response(resp, key: "bookmarks", type: UserBookmark)
8
+ end
9
+
10
+ # TODO: API error: "reason": "not-found"
11
+ def add(collection_id:, item_id:)
12
+ put("v3/market/user/bookmark_add?collection_id=#{collection_id}&item_id=#{item_id}")
13
+ end
14
+
15
+ def remove(id:)
16
+ delete("v3/market/user/bookmark_remove?id=#{id}")
17
+ end
18
+
19
+ # TODO: bookmarks_for_items
20
+ # TODO: item_ids: comma separated "12312312,123123123,12312312"
21
+ def for_items(item_ids:)
22
+ Object.new get("v3/market/user/bookmarks_for_items?item_ids=#{item_ids}").body
23
+ end
24
+
25
+ # TODO: add to CollectionResource
26
+ # TODO: API error: "reason": "not-found"
27
+ def collection_create(name:, site:, description:, is_public: false)
28
+ Object.new post("v3/market/user/collection_create \
29
+ ?name=#{name}&site=#{site} \
30
+ &public=#{is_public} \
31
+ &description=#{description}".gsub(/\s+/, "")).body
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Envato
4
+ class ItemResource < Resource
5
+ def prices(item_id:)
6
+ resp = get("v1/market/item-prices:#{item_id}.json")
7
+ Collection.from_response(resp, key: "item-prices", type: ItemPrice)
8
+ end
9
+
10
+ def download(item_id:, purchase_code:, shorten_url: true)
11
+ Object.new get("v3/market/buyer/download \
12
+ ?item_id=#{item_id} \
13
+ &purchase_code=#{purchase_code} \
14
+ &shorten_url=#{shorten_url}".gsub(/\s+/, "")).body
15
+ end
16
+
17
+ # TODO: filter_by: wordpress-plugins | wordpress-themes
18
+ def list_purchases(filter_by: "wordpress-themes", page: 1, details: false)
19
+ resp = get("v3/market/buyer/list-purchases \
20
+ ?filter_by=#{filter_by} \
21
+ &page=#{page} \
22
+ &details=#{details}".gsub(/\s+/, ""))
23
+ Collection.from_response(resp, key: "results", type: Item)
24
+ end
25
+
26
+ def purchase(code:)
27
+ Object.new get("v3/market/buyer/purchase?code=#{code}").body
28
+ end
29
+
30
+ def purchases
31
+ resp = get("v3/market/buyer/purchases")
32
+ Collection.from_response(resp, key: "purchases", type: Item)
33
+ end
34
+
35
+ def version(id:)
36
+ ItemVersion.new get("v3/market/catalog/item-version?id=#{id}").body
37
+ end
38
+
39
+ def info(id:)
40
+ Item.new get("v3/market/catalog/item?id=#{id}").body
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,131 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Envato
4
+ class MarketResource < Resource
5
+ def user(username:)
6
+ Object.new get("v1/market/user:#{username}").body
7
+ end
8
+
9
+ # TODO: move methods to CategoriesResource
10
+ def categories(site:)
11
+ resp = get("v1/market/categories:#{site}.json")
12
+ Collection.from_response(resp, key: "categories", type: Category)
13
+ end
14
+
15
+ def categories_themeforest
16
+ categories(site: "themeforest")
17
+ end
18
+
19
+ def categories_photodune
20
+ categories(site: "photodune")
21
+ end
22
+
23
+ def categories_codecanyon
24
+ categories(site: "codecanyon")
25
+ end
26
+
27
+ def categories_videohive
28
+ categories(site: "videohive")
29
+ end
30
+
31
+ def categories_audiojungle
32
+ categories(site: "audiojungle")
33
+ end
34
+
35
+ def categories_graphicriver
36
+ categories(site: "graphicriver")
37
+ end
38
+
39
+ def categories_3docean
40
+ categories(site: "3docean")
41
+ end
42
+
43
+ # TODO: Features.new
44
+ def features(site:)
45
+ Object.new get("v1/market/features:#{site}.json").body
46
+ end
47
+
48
+ def features_themeforest
49
+ features(site: "themeforest")
50
+ end
51
+
52
+ def features_photodune
53
+ features(site: "photodune")
54
+ end
55
+
56
+ def features_codecanyon
57
+ features(site: "codecanyon")
58
+ end
59
+
60
+ def features_videohive
61
+ features(site: "videohive")
62
+ end
63
+
64
+ def features_audiojungle
65
+ features(site: "audiojungle")
66
+ end
67
+
68
+ def features_graphicriver
69
+ features(site: "graphicriver")
70
+ end
71
+
72
+ def features_3docean
73
+ features(site: "3docean")
74
+ end
75
+
76
+ def popular_items(site:)
77
+ Object.new get("v1/market/popular:#{site}.json").body
78
+ end
79
+
80
+ def popular_items_themeforest
81
+ popular_items(site: "themeforest")
82
+ end
83
+
84
+ def popular_items_photodune
85
+ popular_items(site: "photodune")
86
+ end
87
+
88
+ def popular_items_codecanyon
89
+ popular_items(site: "codecanyon")
90
+ end
91
+
92
+ def popular_items_videohive
93
+ popular_items(site: "videohive")
94
+ end
95
+
96
+ def popular_items_audiojungle
97
+ popular_items(site: "audiojungle")
98
+ end
99
+
100
+ def popular_items_graphicriver
101
+ popular_items(site: "graphicriver")
102
+ end
103
+
104
+ def popular_items_3docean
105
+ popular_items(site: "3docean")
106
+ end
107
+
108
+ # TODO: add themeforest, graphicriver, etc.
109
+ def new_files(site:, category:)
110
+ resp = get("v1/market/new-files:#{site},#{category}.json")
111
+ Collection.from_response(resp, key: "new-files", type: Item)
112
+ end
113
+
114
+ # TODO: add themeforest, etc.
115
+ def new_files_graphicriver(category:)
116
+ new_files(site: "graphicriver", category: category)
117
+ end
118
+
119
+ def new_files_from_user(username:, site:)
120
+ Object.new get("v1/market/new-files-from-user:#{username},#{site}.json")
121
+ end
122
+
123
+ def random_new_files(site:)
124
+ Object.new get("v1/market/random-new-files:#{site}.json")
125
+ end
126
+
127
+ def collection(id:, page: 1)
128
+ Object.new get("v3/market/catalog/collection?id=#{id}&page=#{page}").body
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Envato
4
+ class MarketsResource < Resource
5
+ def number_of_files(site:)
6
+ Object.new get("v1/market/number-of-files:#{site}.json").body
7
+ end
8
+
9
+ def total_themeforest
10
+ number_of_files(site: "themeforest")
11
+ end
12
+
13
+ def total_photodune
14
+ number_of_files(site: "photodune")
15
+ end
16
+
17
+ def total_codecanyon
18
+ number_of_files(site: "codecanyon")
19
+ end
20
+
21
+ def total_videohive
22
+ number_of_files(site: "videohive")
23
+ end
24
+
25
+ def total_audiojungle
26
+ number_of_files(site: "audiojungle")
27
+ end
28
+
29
+ def total_graphicriver
30
+ number_of_files(site: "graphicriver")
31
+ end
32
+
33
+ def total_3docean
34
+ number_of_files(site: "3docean")
35
+ end
36
+
37
+ def total_items
38
+ Object.new get("v1/market/total-items.json").body
39
+ end
40
+ alias total total_items
41
+ end
42
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Envato
4
+ class SearchResource < Resource
5
+ def more_like_this(item_id:, page: 1, page_size: 10)
6
+ resp = get("v1/discovery/search/search/more_like_this?item_id=#{item_id}&page=#{page}&page_size=#{page_size}")
7
+ Collection.from_response(resp, key: "matches", type: Item)
8
+ end
9
+ alias like more_like_this
10
+
11
+ def comments(item_id:, page: 1, page_size: 10)
12
+ resp = get("v1/discovery/search/search/comment?item_id=#{item_id}&page=#{page}&page_size=#{page_size}")
13
+ Collection.from_response(resp, key: "matches", type: Comment)
14
+ end
15
+
16
+ def item
17
+ resp = get("v1/discovery/search/search/item")
18
+ Collection.from_response(resp, key: "matches", type: Item)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Envato
4
+ class UserResource < Resource
5
+ def statement
6
+ UserStatement.new get("v3/market/user/statement").body
7
+ end
8
+
9
+ def collections
10
+ resp = get("v3/market/user/collections")
11
+ Collection.from_response(resp, key: "collections", type: UserCollection)
12
+ end
13
+
14
+ def collection(id:)
15
+ resp = get("v3/market/user/collection?id=#{id}")
16
+ Collection.from_response(resp, key: "items", type: CollectionItem)
17
+ end
18
+
19
+ def items(username:)
20
+ resp = get("v1/market/user-items-by-site:#{username}.json")
21
+ Collection.from_response(resp, key: "user-items-by-site", type: Item)
22
+ end
23
+
24
+ def badges(username:)
25
+ resp = get("v1/market/user-badges:#{username}.json")
26
+ Collection.from_response(resp, key: "user-badges", type: UserBadge)
27
+ end
28
+
29
+ def earnings_and_sales
30
+ Object.new get("v1/market/private/user/earnings-and-sales-by-month.json").body
31
+ end
32
+ alias sales_and_earnings earnings_and_sales
33
+
34
+ def account
35
+ UserAccount.new get("/v1/market/private/user/account.json").body
36
+ end
37
+
38
+ def name
39
+ Object.new get("v1/market/private/user/username.json").body
40
+ end
41
+ alias username name
42
+
43
+ def email
44
+ Object.new get("v1/market/private/user/email.json").body
45
+ end
46
+
47
+ def sales
48
+ Object.new get("v1/market/private/author/sales").body
49
+ end
50
+
51
+ def sale(code:)
52
+ UserSale.new get("v3/market/author/sale?code=#{code}").body
53
+ end
54
+
55
+ # TODO: rename and move to CollectionResource
56
+ def add_to_favorite(item_id:)
57
+ put("v3/market/user/favourite_collection_add?item_id=#{item_id}")
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Envato
4
+ class UsersResource < Resource
5
+ def total
6
+ UsersTotal.new get("v1/market/total-users.json").body
7
+ end
8
+ alias totat_users total
9
+ end
10
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Envato
4
+ major = 1
5
+ minor = 0
6
+ patch = 0
7
+ VERSION = "#{major}.#{minor}.#{patch}"
8
+ end
data/lib/envato.rb ADDED
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "addressable/uri"
4
+ require "faraday"
5
+ require "envato/version"
6
+
7
+ module Envato
8
+ autoload :Client, "envato/client"
9
+ autoload :Object, "envato/object"
10
+ autoload :Resource, "envato/resource"
11
+ autoload :Collection, "envato/collection"
12
+ autoload :Error, "envato/error"
13
+
14
+ autoload :UserResource, "envato/resources/user"
15
+ autoload :UsersResource, "envato/resources/users"
16
+ autoload :MarketResource, "envato/resources/market"
17
+ autoload :MarketsResource, "envato/resources/markets"
18
+ autoload :SearchResource, "envato/resources/search"
19
+ autoload :BookmarksResource, "envato/resources/bookmarks"
20
+ autoload :ItemResource, "envato/resources/item"
21
+
22
+ autoload :User, "envato/objects/types"
23
+ autoload :UserAccount, "envato/objects/types"
24
+ autoload :UserStatement, "envato/objects/types"
25
+ autoload :UserList, "envato/objects/types"
26
+ autoload :UserStatement, "envato/objects/types"
27
+ autoload :UserCollection, "envato/objects/types"
28
+ autoload :UserBookmark, "envato/objects/types"
29
+
30
+ autoload :UsersTotal, "envato/objects/types"
31
+
32
+ autoload :SearchMatch, "envato/objects/types"
33
+
34
+ autoload :CollectionItem, "envato/objects/types"
35
+
36
+ autoload :Item, "envato/objects/types"
37
+ autoload :ItemPrice, "envato/objects/types"
38
+ autoload :ItemVersion, "envato/objects/types"
39
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+ require "envato"
5
+
6
+ RSpec.describe "#bookmarks.list" do
7
+ subject(:resp) do
8
+ VCR.use_cassette("bookmarks_list") do
9
+ @envato.bookmarks.list
10
+ end
11
+ end
12
+
13
+ it { expect(resp).to be_instance_of(Envato::Collection) }
14
+ it { expect(resp.data.first).to be_instance_of(Envato::UserBookmark) }
15
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+ require "envato"
5
+
6
+ RSpec.describe Envato::Client do
7
+ context "with valid token" do
8
+ describe "#user", :vcr do
9
+ it "name" do
10
+ allow(@envato.user)
11
+ .to receive(:name)
12
+ .and_return(Envato::UserResource)
13
+ end
14
+ end
15
+ end
16
+
17
+ context "without token" do
18
+ it do
19
+ expect { described_class.new }.to raise_error(ArgumentError)
20
+ end
21
+ end
22
+ end
23
+
24
+ RSpec.describe "#VERSION" do
25
+ it { expect(Envato::VERSION).to eq "1.0.0" }
26
+ end
data/spec/item_spec.rb ADDED
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+ require "envato"
5
+
6
+ RSpec.describe "#item.info" do
7
+ context "with id param" do
8
+ subject(:resp) do
9
+ VCR.use_cassette("item_info") do
10
+ @envato.item.info(id: "5556590")
11
+ end
12
+ end
13
+
14
+ it { expect(resp).to be_an(Envato::Item) }
15
+ it { expect(resp.tags).to be_an(Array) }
16
+ it { expect(resp.attributes).to be_an(Array) }
17
+ it { expect(resp.previews).to be_an(OpenStruct) }
18
+ it { expect(resp.site).to eq("themeforest.net") }
19
+ end
20
+
21
+ context "without id param" do
22
+ subject(:resp) do
23
+ VCR.use_cassette("item_info") do
24
+ @envato.item.info
25
+ end
26
+ end
27
+
28
+ it { expect { resp }.to raise_error(ArgumentError) }
29
+ end
30
+ end
31
+
32
+ RSpec.describe "#item.version" do
33
+ context "with id param" do
34
+ subject(:resp) do
35
+ VCR.use_cassette("item_version") do
36
+ @envato.item.version(id: "5556590")
37
+ end
38
+ end
39
+
40
+ it { expect(resp).to be_instance_of(Envato::ItemVersion) }
41
+ end
42
+
43
+ context "without id param" do
44
+ subject(:resp) do
45
+ VCR.use_cassette("item_version") do
46
+ @envato.item.version
47
+ end
48
+ end
49
+
50
+ it { expect { resp }.to raise_error(ArgumentError) }
51
+ end
52
+ end
53
+
54
+ RSpec.describe "#item.prices" do
55
+ context "with id param" do
56
+ subject(:resp) do
57
+ VCR.use_cassette("item_prices") do
58
+ @envato.item.prices(item_id: "5556590")
59
+ end
60
+ end
61
+
62
+ it { expect(resp).to be_instance_of(Envato::Collection) }
63
+ it { expect(resp.data.first).to be_instance_of(Envato::ItemPrice) }
64
+ end
65
+
66
+ context "without id param" do
67
+ it { expect { @envato.item.prices }.to raise_error(ArgumentError, /missing keyword/) }
68
+ end
69
+ end
70
+
71
+ RSpec.describe "#item.purchases" do
72
+ subject(:resp) do
73
+ VCR.use_cassette("item_purchases") do
74
+ @envato.item.purchases
75
+ end
76
+ end
77
+
78
+ it { expect(resp).to be_instance_of(Envato::Collection) }
79
+ end
80
+
81
+ RSpec.describe "#item.list_purchases" do
82
+ subject(:resp) do
83
+ VCR.use_cassette("item_list_purchases") do
84
+ @envato.item.list_purchases
85
+ end
86
+ end
87
+
88
+ it { expect(resp).to be_instance_of(Envato::Collection) }
89
+ it { expect(resp.data.count).to be_instance_of(Integer) }
90
+ end
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+ require "envato"
5
+
6
+ RSpec.describe "#market.categories" do
7
+ context "when site is themeforest" do
8
+ subject(:resp) do
9
+ VCR.use_cassette("market_categories_themeforest") do
10
+ @envato.market.categories site: "themeforest"
11
+ end
12
+ end
13
+
14
+ it { expect(resp).to be_instance_of(Envato::Collection) }
15
+ it { expect(resp.data.first).to be_instance_of(Envato::Category) }
16
+ it { expect(resp.data.first.name).to eq "Site Templates" }
17
+ it { expect(resp.data.first.path).to eq "site-templates" }
18
+ end
19
+
20
+ context "when site is graphicriver" do
21
+ subject(:resp) do
22
+ VCR.use_cassette("market_categories_graphicriver") do
23
+ @envato.market.categories_graphicriver
24
+ end
25
+ end
26
+
27
+ it { expect(resp).to be_instance_of(Envato::Collection) }
28
+ it { expect(resp.data.first).to be_instance_of(Envato::Category) }
29
+ it { expect(resp.data.first.name).to eq "Graphics" }
30
+ it { expect(resp.data.first.path).to eq "graphics" }
31
+ end
32
+ end
33
+
34
+ RSpec.describe "#market.features" do
35
+ context "when site is themeforest" do
36
+ subject(:resp) do
37
+ VCR.use_cassette("market_features_themeforest") do
38
+ @envato.market.features site: "themeforest"
39
+ end
40
+ end
41
+
42
+ # TODO: Object to Features
43
+ it { expect(resp).to be_an(Envato::Object) }
44
+ it { expect(resp.features.free_file).to be_an OpenStruct }
45
+ it { expect(resp.features.featured_file).to be_an OpenStruct }
46
+ it { expect(resp.features.featured_author).to be_an OpenStruct }
47
+ end
48
+
49
+ context "when site is graphicriver" do
50
+ subject(:resp) do
51
+ VCR.use_cassette("market_features_graphicriver") do
52
+ @envato.market.features_graphicriver
53
+ end
54
+ end
55
+
56
+ it { expect(resp).to be_instance_of(Envato::Object) }
57
+ it { expect(resp.features.free_file).to be_an OpenStruct }
58
+ it { expect(resp.features.featured_file).to be_an OpenStruct }
59
+ it { expect(resp.features.featured_author).to be_an OpenStruct }
60
+ end
61
+ end
62
+
63
+ RSpec.describe "#market.new_files" do
64
+ context "when site is themeforest" do
65
+ subject(:resp) do
66
+ VCR.use_cassette("market_new_files") do
67
+ @envato.market.new_files(site: "themeforest", category: "site-templates")
68
+ end
69
+ end
70
+
71
+ it { expect(resp).to be_instance_of(Envato::Collection) }
72
+ it { expect(resp.data.first).to be_an OpenStruct }
73
+ end
74
+
75
+ context "when site is graphicriver" do
76
+ context "ant category is graphics" do
77
+ subject(:resp) do
78
+ VCR.use_cassette("market_new_files_graphicriver_graphics") do
79
+ @envato.market.new_files_graphicriver category: "graphics"
80
+ end
81
+ end
82
+
83
+ it { expect(resp).to be_instance_of(Envato::Collection) }
84
+ it { expect(resp.data.first).to be_an OpenStruct }
85
+ end
86
+ end
87
+ end
88
+
89
+ RSpec.describe "#market.popular_items" do
90
+ subject(:resp) do
91
+ VCR.use_cassette("market_popular_items_themeforest") do
92
+ @envato.market.popular_items site: "themeforest"
93
+ end
94
+ end
95
+
96
+ it { expect(resp).to be_instance_of(Envato::Object) }
97
+ it { expect(resp.popular).to be_instance_of(OpenStruct) }
98
+ it { expect(resp.popular.items_last_week).to be_instance_of(Array) }
99
+ it { expect(resp.popular.items_last_week.first.id).not_to be(nil) }
100
+ end