typekit_client 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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 02f351c322a027c5490e836326c451eb19bb0374
4
+ data.tar.gz: 286df5e110bde5b1be3a821739acca9ae61fb32d
5
+ SHA512:
6
+ metadata.gz: 1f115fa302f680754b71796d2ee836344bd4c3320d99b18dda7c165d1ed70ffc90881d3639c0ec5dde73f32a8a401d963ddac20cf756f8845f3c41e109af1feb
7
+ data.tar.gz: db216f62aa8195763b8726ebe1be2a757e1f23c1eecb27cd13fd3ea9275cf90e3364302d4613ff30f58433af072ab06b8633d2a98114104ecc5026d2923840c6
data/.gitignore ADDED
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ # rspec failure tracking
11
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.4.1
5
+ before_install: gem install bundler -v 1.16.0
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in typekit_client.gemspec
6
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2018 Thirukonda Surendran,Koushic Babu
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,43 @@
1
+ # TypekitClient
2
+
3
+ Ruby CLI app for Adobe TypeKit https://typekit.com/docs/api/v1/:format/kits
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'typekit_client'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install typekit_client
20
+
21
+ ## Usage
22
+
23
+ To view the list of available commands, type:
24
+
25
+ $ typekit_client help
26
+
27
+ All the commands require user token for authentication. Please input token when prompted. The user token can be obtained from https://typekit.com/account/tokens
28
+
29
+ To run the Rspec tests, run:
30
+
31
+ $ rake
32
+
33
+ ## Contributing
34
+
35
+ Bug reports and pull requests are welcome on GitHub at https://github.com/koushic88/typekit_client. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
36
+
37
+ ## License
38
+
39
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
40
+
41
+ ## Code of Conduct
42
+
43
+ Everyone interacting in the TypekitClient project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/koushic88/typekit_client/blob/master/CODE_OF_CONDUCT.md).
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+ require_relative '../lib/typekit_client'
3
+
4
+ # Start the CLI
5
+ TypekitClient::CLI.start ARGV
@@ -0,0 +1,5 @@
1
+ require "typekit_client/version"
2
+
3
+ require 'typekit_client/cli'
4
+ require 'typekit_client/typekit_api'
5
+ require 'typekit_client/http_request'
@@ -0,0 +1,100 @@
1
+ require "thor"
2
+ require "typekit_client/typekit_api"
3
+ require 'filecache'
4
+ require 'colorize'
5
+
6
+ module TypekitClient
7
+
8
+ TOKEN_CACHE = FileCache.new("auth-token", "/tmp/caches", 1800, 3)
9
+
10
+ class CLI < Thor
11
+
12
+ desc "kits", "Returns a list of kits owned by the authenticating user"
13
+ option :format, default: 'json', enum: %w(json xml yaml)
14
+ def kits
15
+ check_auth_token
16
+ TypekitClient::TypekitAPI.kits(options[:format])
17
+ end
18
+
19
+ desc "kit KIT_ID", "Returns information about the draft version of the kit KIT_ID"
20
+ option :format, default: 'json', enum: %w(json xml yaml)
21
+ def kit(kit_id)
22
+ check_auth_token
23
+ TypekitClient::TypekitAPI.kit(kit_id, options[:format])
24
+ end
25
+
26
+ desc "delete_kit KIT_ID", "Deletes a kit KIT_ID"
27
+ option :format, default: 'json', enum: %w(json xml yaml)
28
+ def delete_kit(kit_id)
29
+ check_auth_token
30
+ TypekitClient::TypekitAPI.delete_kit(kit_id, options[:format])
31
+ end
32
+
33
+ desc "publish_kit KIT_ID", "Publishes the current draft version of a kit KIT_ID"
34
+ option :format, default: 'json', enum: %w(json xml yaml)
35
+ def publish_kit(kit_id)
36
+ check_auth_token
37
+ TypekitClient::TypekitAPI.publish_kit(kit_id, options[:format])
38
+ end
39
+
40
+ desc "published_kit KIT_ID", "Returns information about the published version of the kit"
41
+ option :format, default: 'json', enum: %w(json xml yaml)
42
+ def published_kit(kit_id)
43
+ check_auth_token
44
+ TypekitClient::TypekitAPI.published_kit(kit_id, options[:format])
45
+ end
46
+
47
+ desc "kit_family KIT_ID FAMILY_ID", "Returns information about a font family FAMILY_ID used in a kit KIT_ID"
48
+ option :format, default: 'json', enum: %w(json xml yaml)
49
+ def kit_family(kit_id, family_id)
50
+ check_auth_token
51
+ TypekitClient::TypekitAPI.family(kit_id, family_id, options[:format])
52
+ end
53
+
54
+ desc "delete_family KIT_ID FAMILY_ID", "Removes font family FAMILY_ID from the kit KIT_ID"
55
+ option :format, default: 'json', enum: %w(json xml yaml)
56
+ def delete_family(kit_id, family_id)
57
+ check_auth_token
58
+ TypekitClient::TypekitAPI.delete_family(kit_id, family_id, options[:format])
59
+ end
60
+
61
+ desc "create_kit", "Creates a new draft kit and returns the updated information"
62
+ option :format, default: 'json', enum: %w(json xml yaml)
63
+ option :name, required: true, desc: 'name of the kit'
64
+ option :domains, required: true, desc: 'comma separated list of domains'
65
+ option :segmented_css_names, default: 'true', enum: %w(true false), desc: 'specify whether families in this kit should use segmented or unsegmented CSS fonts'
66
+ option :families, desc: 'font family to be included in the app, format: --families=id:123,variations:n1\;id:456,variations:i7'
67
+ def create_kit
68
+ check_auth_token
69
+ TypekitClient::TypekitAPI.create_kit(options)
70
+ end
71
+
72
+ desc "add_family KIT_ID FAMILY_ID", "Adds or Modifies existing family to the existing kit KIT_ID, returns the updated information"
73
+ option :format, default: 'json', enum: %w(json xml yaml)
74
+ option :subset, default: 'default', enum: %w(default all), desc: 'character subset to use'
75
+ option :variations, desc: 'a list of font variations to use - comma seperated values'
76
+ def add_family(kit_id, family_id)
77
+ check_auth_token
78
+ TypekitClient::TypekitAPI.add_family(kit_id, family_id, options)
79
+ end
80
+
81
+ no_commands do
82
+
83
+ # This helper method checks if the auth token exists in the file cache. If token doesn't exists, it prompts user to
84
+ # input the auth token, and it gets cached.
85
+ #
86
+ # Returns authentication token
87
+ #
88
+ def check_auth_token
89
+ token = TypekitClient::TOKEN_CACHE.get("token")
90
+ if !token
91
+ print "Authentication token required, Get token from https://typekit.com/account/tokens :".red
92
+ token = STDIN.gets.chomp
93
+ TypekitClient::TOKEN_CACHE.set("token", token.strip)
94
+ end
95
+
96
+ token
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,69 @@
1
+ require 'net/http'
2
+ require 'json'
3
+ require 'rack/utils'
4
+
5
+ module TypekitClient
6
+ module HttpRequest
7
+
8
+ BASE_URI = 'https://typekit.com/api/v1'
9
+
10
+ # This allow us to not pass strings to determine the request type.
11
+ REQUEST_TYPE = {
12
+ :GET => Net::HTTP::Get,
13
+ :POST => Net::HTTP::Post,
14
+ :DELETE => Net::HTTP::Delete
15
+ }
16
+
17
+ # Public: This function makes network calls to the Typekit API depending on the
18
+ # parameters passed and returns the response from the server.
19
+ # The function can make 3 types of HTTP calls including get, post, delete
20
+ #
21
+ # uri_string- The uri string to be appended to the base uri
22
+ # type- the type of HTTP request to make
23
+ # format- format of the response data
24
+ # body- hash to set as request body for POST requests
25
+ #
26
+ # Example:
27
+ #
28
+ # request('kits',:GET, 'json', {kits: ''})
29
+ # => # Net::HTTPResponse object
30
+ #
31
+ # It returns the response from the request if there are no runtime errors
32
+ #
33
+ def self.request(uri_string, type, format, body=nil)
34
+
35
+ request = REQUEST_TYPE[type].new(URI.parse("#{BASE_URI}/#{format}/#{uri_string}"))
36
+ request['X-Typekit-Token'] = TypekitClient::TOKEN_CACHE.get("token")
37
+
38
+ request.body = Rack::Utils.build_nested_query(body) if body
39
+
40
+ response = execute_request(request)
41
+
42
+ # clear the cache if the response code is not 401(unauthorized)
43
+ TypekitClient::TOKEN_CACHE.clear if response.code == '401'
44
+
45
+ return response
46
+ rescue SocketError
47
+ puts "Socket Error, Please check your internet connection.".red
48
+ rescue Net::OpenTimeout
49
+ puts "The request timed out when trying to connect, please check your connection.".red
50
+ end
51
+
52
+ private
53
+
54
+ # Private: Makes http calls with given request. It can be any http
55
+ # request such as get, post, delete.
56
+ #
57
+ # request- request instance such as Net::HTTP::Get.new(), Net::HTTP::POST.new()
58
+ #
59
+ # Returns the response object
60
+ # Raises error when there is a timeout issue or internet connection is down
61
+ def self.execute_request(request)
62
+ http = Net::HTTP.new(request.uri.host, request.uri.port)
63
+ http.use_ssl = true if request.uri.to_s.include? 'https'
64
+
65
+ http.request(request)
66
+ end
67
+
68
+ end
69
+ end
@@ -0,0 +1,249 @@
1
+ require "typekit_client/http_request"
2
+ require 'colorize'
3
+
4
+ module TypekitClient
5
+ module TypekitAPI
6
+
7
+ # Public: This helper method makes http request and prints out the list of kits
8
+ #
9
+ # format- The user requested format, set to JSON by default
10
+ #
11
+ # Example:
12
+ #
13
+ # kits('json')
14
+ #
15
+ # If it is a success, it prints the response body based on the specified format
16
+ # If it is a failure, it prints out error status code and message
17
+ #
18
+ def self.kits(format)
19
+ uri_string = 'kits'
20
+ response = TypekitClient::HttpRequest.request(uri_string, :GET, format)
21
+
22
+ print_response(response)
23
+ end
24
+
25
+ # Public: This helper method makes http request and prints out the draft version of the kit for the given kit id
26
+ #
27
+ # kit_id- The kit id to find the details for
28
+ # format- The user requested format, set to JSON by default
29
+ #
30
+ # Example:
31
+ #
32
+ # kit('bsz4xuy', 'json')
33
+ #
34
+ # If it is a success, it prints the kit details based on the specified format
35
+ # If it is a failure, it prints out error status code and message
36
+ #
37
+ def self.kit(kit_id, format)
38
+ uri_string = "kits/#{kit_id}"
39
+ response = TypekitClient::HttpRequest.request(uri_string, :GET, format)
40
+
41
+ print_response(response)
42
+ end
43
+
44
+ # Public: This helper method makes http request to create a new kit
45
+ #
46
+ # options- The options hash containing user inputs
47
+ #
48
+ # Example:
49
+ #
50
+ # create_kit({format: 'json', name: 'test'})
51
+ #
52
+ # If it is a success, it prints the newly created kit details based on the specified format
53
+ # If it is a failure, it prints out error status code and message
54
+ #
55
+ def self.create_kit(options)
56
+
57
+ body = {
58
+ name: options[:name],
59
+ domains: options[:domains],
60
+ segmented_css_names: options[:segmented_css_names]
61
+ }
62
+
63
+ body[:families] = parse_families(options[:families]) if options[:families]
64
+
65
+ uri_string = 'kits'
66
+ response = TypekitClient::HttpRequest.request(uri_string, :POST, options[:format], body)
67
+ print_response(response)
68
+ end
69
+
70
+ # Public: This helper method makes http request and deletes the kit for the given kit id
71
+ #
72
+ # kit_id- The id of the kit to delete
73
+ # format- The user requested format, set to JSON by default
74
+ #
75
+ # Example:
76
+ #
77
+ # delete_kit('bsz4xuy', 'json')
78
+ #
79
+ # If it is a success, it prints the success message
80
+ # If it is a failure, it prints out error status code and message
81
+ #
82
+ def self.delete_kit(kit_id, format)
83
+ uri_string = "kits/#{kit_id}"
84
+ response = TypekitClient::HttpRequest.request(uri_string, :DELETE, format)
85
+
86
+ print_response(response)
87
+ end
88
+
89
+ # Public: This helper method makes http request and prints out the font family details for the given
90
+ # font id and the family id
91
+ #
92
+ # kit_id- The kit id to find the details for
93
+ # family_id- The font family id for the kit
94
+ # format- The user requested format, set to JSON by default
95
+ #
96
+ # Example:
97
+ #
98
+ # family('bsz4xuy', 'myvg', 'json')
99
+ #
100
+ # If it is a success, it prints the font family details based on the specified format
101
+ # If it is a failure, it prints out error status code and message
102
+ #
103
+ def self.family(kit_id, family_id, format)
104
+ uri_string = "kits/#{kit_id}/families/#{family_id}"
105
+ response = TypekitClient::HttpRequest.request(uri_string, :GET, format)
106
+
107
+ print_response(response)
108
+ end
109
+
110
+ # Public: This helper method makes http request to add new font family to kit
111
+ #
112
+ # kit_id- The kit id to add the font family
113
+ # family_id- The font family id to be added
114
+ # options- The options hash containing user inputs
115
+ #
116
+ # Example:
117
+ #
118
+ # add_family('bsz4xuy', 'myvg', {format: 'json', subset: 'default'})
119
+ #
120
+ # If it is a success, it prints the newly added font family details based on the specified format
121
+ # If it is a failure, it prints out error status code and message
122
+ #
123
+ def self.add_family(kit_id, family_id, options)
124
+
125
+ body = { subset: options[:subset] }
126
+ body[:variations] = options[:variations] if options[:variations]
127
+
128
+ uri_string = "kits/#{kit_id}/families/#{family_id}"
129
+ response = TypekitClient::HttpRequest.request(uri_string, :POST, options[:format], body)
130
+ print_response(response)
131
+ end
132
+
133
+ # Public: This helper method makes http request to publish the draft version of the kit
134
+ #
135
+ # kit_id- The id of the kit to publish
136
+ # format- The user requested format, set to JSON by default
137
+ #
138
+ # Example:
139
+ #
140
+ # publish_kit('bsz4xuy', 'json')
141
+ #
142
+ # If it is a success, it prints the published date in specified format
143
+ # If it is a failure, it prints out error status code and message
144
+ #
145
+ def self.publish_kit(kit_id, format)
146
+ uri_string = "kits/#{kit_id}/publish"
147
+ response = TypekitClient::HttpRequest.request(uri_string, :POST, format)
148
+
149
+ print_response(response)
150
+ end
151
+
152
+ # Public: This helper method makes http request and prints out the published version of kit for the given kit id
153
+ # If token is not provided, it will display only public info
154
+ # pass-in token in the options hash to get all info with proper authentication
155
+ #
156
+ # kit_id- The kit id to find the details for
157
+ # format- The user requested format, set to JSON by default
158
+ #
159
+ # Example:
160
+ #
161
+ # published_kit('bsz4xuy', 'json')
162
+ #
163
+ # If it is a success, it prints the kit details based on the specified format
164
+ # If it is a failure, it prints out error status code and message
165
+ #
166
+ def self.published_kit(kit_id, format)
167
+ uri_string = "kits/#{kit_id}/published"
168
+ response = TypekitClient::HttpRequest.request(uri_string, :GET, format)
169
+
170
+ print_response(response)
171
+ end
172
+
173
+ # Public: This helper method makes http request to delete font family from kit
174
+ #
175
+ # kit_id- The kit id to delete the family from
176
+ # family_id- The font family id in the kit
177
+ # format- The user requested format, set to JSON by default
178
+ #
179
+ # Example:
180
+ #
181
+ # delete_family('bsz4xuy', 'myvg', 'json')
182
+ #
183
+ # If it is a success, it prints success message
184
+ # If it is a failure, it prints out error status code and message
185
+ #
186
+ def self.delete_family(kit_id, family_id, format)
187
+ uri_string = "kits/#{kit_id}/families/#{family_id}"
188
+ response = TypekitClient::HttpRequest.request(uri_string, :DELETE, format)
189
+
190
+ print_response(response)
191
+ end
192
+
193
+
194
+ private
195
+
196
+ # Private: This helper method prints out the response body based on the response code
197
+ #
198
+ # response- The http response object from the http request call
199
+ #
200
+ # Example:
201
+ #
202
+ # print_response(Net::HTTPResponse)
203
+ #
204
+ # If the status code is 200, it prints out the response body based on the content-type
205
+ # If it is a failure, it prints out error status code and message
206
+ #
207
+ def self.print_response(response)
208
+ if response.code == '200'
209
+ if response.body.empty?
210
+ puts 'The command ran successfully'
211
+ end
212
+ if response['content-type'] == 'application/json; charset=utf-8'
213
+ puts JSON.pretty_generate(JSON.parse(response.body))
214
+ else
215
+ puts response.body
216
+ end
217
+ else
218
+ puts "The following error occurred while running the command:#{response.code}, #{JSON.parse(response.body)['errors']}".red
219
+ end
220
+ end
221
+
222
+ # Private: This helper method parses families input string and converts it to a hash
223
+ #
224
+ # families- The user input families string in the format 'id:abcd,variations:n2;id:2,variations:i7'
225
+ #
226
+ # Example:
227
+ #
228
+ # parse_families('id:abcd,variations:n2;id:2,variations:i7')
229
+ # => {"0"=>{"id"=>"1", "variations"=>"n2"}, "1"=>{"id"=>"2", "variations"=>"i7"}}
230
+ #
231
+ # Returns equivalent hash for the string
232
+ #
233
+ def self.parse_families(families)
234
+
235
+ family_list = families.split(';')
236
+ family_hash = {}
237
+
238
+ family_list.each_with_index do |family, index|
239
+ family_hash[index.to_s] = family.split(',').each_with_object({}) { |str, attribute_hash|
240
+ tmp = str.split(':')
241
+ attribute_hash[tmp[0]] = tmp[1] if %w(id variations subset).include? tmp[0]
242
+ }
243
+ end
244
+
245
+ family_hash
246
+ end
247
+
248
+ end
249
+ end
@@ -0,0 +1,3 @@
1
+ module TypekitClient
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,92 @@
1
+ RSpec.describe TypekitClient::HttpRequest do
2
+
3
+ describe '#execute_request' do
4
+ let (:http) { Net::HTTP::Post.new(URI.parse('https://adobe.api.com')) }
5
+ let (:actual) { subject.execute_request(http) }
6
+
7
+ before do
8
+ allow_any_instance_of(Net::HTTP).to receive(:request) { Net::HTTPOK.new('get', '200', 'successful') }
9
+ end
10
+
11
+ context 'with get request' do
12
+ it 'checks response of authorized rest call' do
13
+ expect(actual).to be_a Net::HTTPOK
14
+ end
15
+
16
+ it 'checks response of unauthorized/invalid credentials rest call' do
17
+ allow_any_instance_of(Net::HTTP).to receive(:request) { Net::HTTPUnauthorized.new('get', '401', 'Unauthorized') }
18
+
19
+ expect(actual).to be_a Net::HTTPUnauthorized
20
+ end
21
+ end
22
+
23
+ context 'when wrong url or no internet' do
24
+ it 'checks for SocketError' do
25
+ allow_any_instance_of(Net::HTTP).to receive(:request).and_raise(SocketError)
26
+
27
+ expect { actual }.to raise_error(SocketError)
28
+ end
29
+ end
30
+ end
31
+
32
+ describe '#request' do
33
+ let(:uri_string) { 'kits' }
34
+
35
+ let (:good_path) { 'http://valid.url' }
36
+
37
+ let(:http_request) { subject.request(uri_string, :GET, 'json') }
38
+
39
+
40
+ context 'when SocketError occurs' do
41
+ before do
42
+ allow(subject).to receive(:execute_request).and_raise(SocketError)
43
+ end
44
+
45
+ it 'raises a StandardError' do
46
+ expect{ actual }.to raise_error(StandardError)
47
+ end
48
+ end
49
+
50
+ context 'when request times out' do
51
+ before do
52
+ allow(subject).to receive(:execute_request).and_raise(Net::OpenTimeout)
53
+ end
54
+
55
+ it 'raises a StandardError' do
56
+ expect{ actual }.to raise_error(StandardError)
57
+ end
58
+ end
59
+
60
+ context 'when response with 200 is returned' do
61
+ let(:request) { object_double("Net::HTTP::Get.new") }
62
+ let(:response) { Net::HTTPSuccess.new('response', '200', '{}') }
63
+
64
+ before do
65
+ allow_any_instance_of(Net::HTTP::Get).to receive(:new).and_return(request)
66
+ allow(subject).to receive(:execute_request) { response }
67
+ end
68
+
69
+ it 'ensures response object is returned' do
70
+ expect(http_request).to eq response
71
+ end
72
+ end
73
+
74
+ context 'when response with 401 is returned' do
75
+ let(:request) { object_double("Net::HTTP::Get.new") }
76
+ let(:response) { Net::HTTPUnauthorized.new('response', '401', '{}') }
77
+
78
+ before do
79
+ allow_any_instance_of(Net::HTTP::Get).to receive(:new).and_return(request)
80
+ allow(subject).to receive(:execute_request) { response }
81
+ end
82
+
83
+ it 'ensures token cache gets cleared' do
84
+ token_cache = object_double("TypekitClient::TOKEN_CACHE", :get => nil, :clear => nil).as_stubbed_const
85
+ expect(http_request).to eq response
86
+ expect(token_cache).to have_received(:get).with("token")
87
+ expect(token_cache).to have_received(:clear)
88
+ end
89
+ end
90
+
91
+ end
92
+ end
@@ -0,0 +1,15 @@
1
+ require "bundler/setup"
2
+ require "typekit_client"
3
+ require 'rack/test'
4
+
5
+ RSpec.configure do |config|
6
+ # Enable flags like --only-failures and --next-failure
7
+ config.example_status_persistence_file_path = ".rspec_status"
8
+
9
+ # Disable RSpec exposing methods globally on `Module` and `main`
10
+ config.disable_monkey_patching!
11
+
12
+ config.expect_with :rspec do |c|
13
+ c.syntax = :expect
14
+ end
15
+ end
@@ -0,0 +1,261 @@
1
+ RSpec.describe TypekitClient::TypekitAPI do
2
+
3
+ describe '#kits' do
4
+
5
+ context 'with successful response from http_request' do
6
+ let(:response) { Net::HTTPSuccess.new('response', '200', '') }
7
+ let(:kits) { subject.kits('json') }
8
+
9
+ it 'prints message if the response has no body' do
10
+ allow(TypekitClient::HttpRequest).to receive(:request) { response }
11
+ allow(response).to receive_message_chain(:body, :empty?).and_return(true)
12
+ expect { kits }.to output(/The command ran successfully/).to_stdout
13
+ end
14
+ end
15
+
16
+ context 'with failure response from http_request' do
17
+ let(:response) { Net::HTTPNotFound.new('response', '404', '') }
18
+ let(:kits) { subject.kits('json') }
19
+
20
+ it 'prints error message' do
21
+ allow(TypekitClient::HttpRequest).to receive(:request) { response }
22
+ allow(response).to receive(:body).and_return("{\"errors\":[\"Not Found\"]}")
23
+ expect { kits }.to output(/The following error occurred while running the command:404/).to_stdout
24
+ end
25
+
26
+ end
27
+ end
28
+
29
+ describe '#kit' do
30
+
31
+ context 'with successful response from http_request' do
32
+ let(:response) { Net::HTTPSuccess.new('response', '200', '') }
33
+ let(:kit) { subject.kit('kit_id', 'json') }
34
+
35
+ it 'prints message if the response has no body' do
36
+ allow(TypekitClient::HttpRequest).to receive(:request) { response }
37
+ allow(response).to receive_message_chain(:body, :empty?).and_return(true)
38
+ expect { kit }.to output(/The command ran successfully/).to_stdout
39
+ end
40
+ end
41
+
42
+ context 'with failure response from http_request' do
43
+ let(:response) { Net::HTTPNotFound.new('response', '404', '') }
44
+ let(:kit) { subject.kit('kit_id', 'json') }
45
+
46
+ it 'prints error message when kit is not found' do
47
+ allow(TypekitClient::HttpRequest).to receive(:request) { response }
48
+ allow(response).to receive(:body).and_return("{\"errors\":[\"Not Found\"]}")
49
+ expect { kit }.to output(/The following error occurred while running the command:404/).to_stdout
50
+ end
51
+
52
+ end
53
+ end
54
+
55
+ describe '#create_kit' do
56
+
57
+ context 'with successful response from http_request' do
58
+ let(:response) { Net::HTTPSuccess.new('response', '200', '') }
59
+ let(:create_kit) { subject.create_kit({ "name" => "test", domains: "http://localhost.com", segmented_css_names: false }) }
60
+
61
+ it 'prints message if the response has no body' do
62
+ allow(TypekitClient::HttpRequest).to receive(:request) { response }
63
+ allow(response).to receive_message_chain(:body, :empty?).and_return(true)
64
+ expect { create_kit }.to output(/The command ran successfully/).to_stdout
65
+ end
66
+ end
67
+
68
+ context 'with failure response from http_request' do
69
+ let(:response) { Net::HTTPForbidden.new('response', '403', '') }
70
+ let(:create_kit) { subject.create_kit({ name: "test", domains: "http://localhost.com", segmented_css_names: false }) }
71
+
72
+ it 'prints error message when 403 is thrown' do
73
+ allow(TypekitClient::HttpRequest).to receive(:request) { response }
74
+ allow(response).to receive(:body).and_return("{\"errors\":[\"Not Found\"]}")
75
+ expect { create_kit }.to output(/The following error occurred while running the command:403/).to_stdout
76
+ end
77
+
78
+ end
79
+ end
80
+
81
+ describe '#delete_kit' do
82
+
83
+ context 'with successful response from http_request' do
84
+ let(:response) { Net::HTTPSuccess.new('response', '200', '') }
85
+ let(:delete_kit) { subject.delete_kit('kit_id', 'json') }
86
+
87
+ it 'prints message if the response has no body' do
88
+ allow(TypekitClient::HttpRequest).to receive(:request) { response }
89
+ allow(response).to receive_message_chain(:body, :empty?).and_return(true)
90
+ expect { delete_kit }.to output(/The command ran successfully/).to_stdout
91
+ end
92
+ end
93
+
94
+ context 'with failure response from http_request' do
95
+ let(:response) { Net::HTTPNotFound.new('response', '404', '') }
96
+ let(:delete_kit) { subject.delete_kit('kit_id', 'json') }
97
+
98
+ it 'prints error message when kit is not found' do
99
+ allow(TypekitClient::HttpRequest).to receive(:request) { response }
100
+ allow(response).to receive(:body).and_return("{\"errors\":[\"Not Found\"]}")
101
+ expect { delete_kit }.to output(/The following error occurred while running the command:404/).to_stdout
102
+ end
103
+
104
+ end
105
+ end
106
+
107
+ describe '#family' do
108
+
109
+ context 'with successful response from http_request' do
110
+ let(:response) { Net::HTTPSuccess.new('response', '200', '') }
111
+ let(:family) { subject.family('kit_id', 'family_id', 'json') }
112
+
113
+ it 'prints message if the response has no body' do
114
+ allow(TypekitClient::HttpRequest).to receive(:request) { response }
115
+ allow(response).to receive_message_chain(:body, :empty?).and_return(true)
116
+ expect { family }.to output(/The command ran successfully/).to_stdout
117
+ end
118
+ end
119
+
120
+ context 'with failure response from http_request' do
121
+ let(:response) { Net::HTTPNotFound.new('response', '404', '') }
122
+ let(:family) { subject.family('kit_id', 'family_id', 'json') }
123
+
124
+ it 'prints error message when kit is not found' do
125
+ allow(TypekitClient::HttpRequest).to receive(:request) { response }
126
+ allow(response).to receive(:body).and_return("{\"errors\":[\"Not Found\"]}")
127
+ expect { family }.to output(/The following error occurred while running the command:404/).to_stdout
128
+ end
129
+
130
+ end
131
+ end
132
+
133
+ describe '#add_family' do
134
+
135
+ context 'with successful response from http_request' do
136
+ let(:response) { Net::HTTPSuccess.new('response', '200', '') }
137
+ let(:add_family) { subject.add_family('kit_id', 'family_id', { name: "test", domains: "http://localhost.com",
138
+ segmented_css_names: false }) }
139
+
140
+ it 'prints message if the response has no body' do
141
+ allow(TypekitClient::HttpRequest).to receive(:request) { response }
142
+ allow(response).to receive_message_chain(:body, :empty?).and_return(true)
143
+ expect { add_family }.to output(/The command ran successfully/).to_stdout
144
+ end
145
+ end
146
+
147
+ context 'with failure response from http_request' do
148
+ let(:response) { Net::HTTPForbidden.new('response', '403', '') }
149
+ let(:add_family) { subject.add_family('kit_id', 'family_id', { name: "test", domains: "http://localhost.com",
150
+ segmented_css_names: false }) }
151
+
152
+ it 'prints error message when 403 error is thrown' do
153
+ allow(TypekitClient::HttpRequest).to receive(:request) { response }
154
+ allow(response).to receive(:body).and_return("{\"errors\":[\"Not Found\"]}")
155
+ expect { add_family }.to output(/The following error occurred while running the command:403/).to_stdout
156
+ end
157
+
158
+ end
159
+ end
160
+
161
+ describe '#publish_kit' do
162
+
163
+ context 'with successful response from http_request' do
164
+ let(:response) { Net::HTTPSuccess.new('response', '200', '') }
165
+ let(:publish_kit) { subject.publish_kit('kit_id', 'json') }
166
+
167
+ it 'prints message if the response has no body' do
168
+ allow(TypekitClient::HttpRequest).to receive(:request) { response }
169
+ allow(response).to receive_message_chain(:body, :empty?).and_return(true)
170
+ expect { publish_kit }.to output(/The command ran successfully/).to_stdout
171
+ end
172
+ end
173
+
174
+ context 'with failure response from http_request' do
175
+ let(:response) { Net::HTTPNotFound.new('response', '404', '') }
176
+ let(:publish_kit) { subject.publish_kit('kit_id', 'json') }
177
+
178
+ it 'prints error message when kit is not found' do
179
+ allow(TypekitClient::HttpRequest).to receive(:request) { response }
180
+ allow(response).to receive(:body).and_return("{\"errors\":[\"Not Found\"]}")
181
+ expect { publish_kit }.to output(/The following error occurred while running the command:404/).to_stdout
182
+ end
183
+
184
+ end
185
+ end
186
+
187
+ describe '#published_kit' do
188
+
189
+ context 'with successful response from http_request' do
190
+ let(:response) { Net::HTTPSuccess.new('response', '200', '') }
191
+ let(:published_kit) { subject.published_kit('kit_id', 'json') }
192
+
193
+ it 'prints message if the response has no body' do
194
+ allow(TypekitClient::HttpRequest).to receive(:request) { response }
195
+ allow(response).to receive_message_chain(:body, :empty?).and_return(true)
196
+ expect { published_kit }.to output(/The command ran successfully/).to_stdout
197
+ end
198
+ end
199
+
200
+ context 'with failure response from http_request' do
201
+ let(:response) { Net::HTTPNotFound.new('response', '404', '') }
202
+ let(:published_kit) { subject.published_kit('kit_id', 'json') }
203
+
204
+ it 'prints error message when kit is not found' do
205
+ allow(TypekitClient::HttpRequest).to receive(:request) { response }
206
+ allow(response).to receive(:body).and_return("{\"errors\":[\"Not Found\"]}")
207
+ expect { published_kit }.to output(/The following error occurred while running the command:404/).to_stdout
208
+ end
209
+
210
+ end
211
+ end
212
+
213
+ describe '#delete_family' do
214
+
215
+ context 'with successful response from http_request' do
216
+ let(:response) { Net::HTTPSuccess.new('response', '200', '') }
217
+ let(:delete_family) { subject.delete_family('kit_id', 'family_id', 'json') }
218
+
219
+ it 'prints message if the response has no body' do
220
+ allow(TypekitClient::HttpRequest).to receive(:request) { response }
221
+ allow(response).to receive_message_chain(:body, :empty?).and_return(true)
222
+ expect { delete_family }.to output(/The command ran successfully/).to_stdout
223
+ end
224
+ end
225
+
226
+ context 'with failure response from http_request' do
227
+ let(:response) { Net::HTTPNotFound.new('response', '404', '') }
228
+ let(:delete_family) { subject.delete_family('kit_id', 'family_id', 'json') }
229
+
230
+ it 'prints error message when kit is not found' do
231
+ allow(TypekitClient::HttpRequest).to receive(:request) { response }
232
+ allow(response).to receive(:body).and_return("{\"errors\":[\"Not Found\"]}")
233
+ expect { delete_family }.to output(/The following error occurred while running the command:404/).to_stdout
234
+ end
235
+
236
+ end
237
+ end
238
+
239
+ describe '#parse_families' do
240
+ it 'returns families hash for the given string' do
241
+
242
+ expected_hash = {
243
+ "0" => {"id"=>"abcd", "variations"=>"n2"},
244
+ "1" =>{"id"=>"2", "variations"=>"i7"}
245
+ }
246
+
247
+ expect(subject.send(:parse_families, 'id:abcd,variations:n2;id:2,variations:i7')).to eq expected_hash
248
+ end
249
+
250
+
251
+ it 'verifies unnecessary params are ignored' do
252
+ expected_hash = {
253
+ "0" => {"id"=>"abcd", "variations"=>"n2"},
254
+ "1" =>{"id"=>"2", "variations"=>"i7"}
255
+ }
256
+
257
+ expect(subject.send(:parse_families, 'id:abcd,variations:n2,invalid_param:invalid_value;id:2,variations:i7')).to eq expected_hash
258
+ end
259
+
260
+ end
261
+ end
@@ -0,0 +1,6 @@
1
+ RSpec.describe TypekitClient do
2
+ it "has a version number" do
3
+ expect(TypekitClient::VERSION).not_to be nil
4
+ end
5
+
6
+ end
@@ -0,0 +1,36 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "typekit_client/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "typekit_client"
8
+ spec.version = TypekitClient::VERSION
9
+ spec.authors = ["Thirukonda Surendran,Koushic Babu"]
10
+ spec.email = ["koushicbabuts@gmail.com"]
11
+
12
+ spec.summary = %q{Typekit Ruby Client}
13
+ spec.description = %q{Ruby CLI client for typekit API}
14
+ spec.homepage = "https://github.com/koushic88/typekit_client"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files`.split("\n")
18
+
19
+ if spec.respond_to?(:metadata)
20
+ spec.metadata['allowed_push_host'] = "https://rubygems.org"
21
+ else
22
+ raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
23
+ end
24
+
25
+ spec.bindir = "exe"
26
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
27
+ spec.require_paths = ["lib"]
28
+
29
+ spec.add_development_dependency 'bundler', '~> 1.16'
30
+ spec.add_development_dependency 'rake', '~> 10.0'
31
+ spec.add_development_dependency 'rspec', '~> 3.0'
32
+ spec.add_development_dependency 'rack-test', '~> 0.8.2'
33
+ spec.add_runtime_dependency 'thor', '0.20.0'
34
+ spec.add_runtime_dependency 'colorize', '0.8.1'
35
+ spec.add_runtime_dependency 'filecache', '1.0.2'
36
+ end
metadata ADDED
@@ -0,0 +1,161 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: typekit_client
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Thirukonda Surendran,Koushic Babu
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2018-01-26 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.16'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.16'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rack-test
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.8.2
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.8.2
69
+ - !ruby/object:Gem::Dependency
70
+ name: thor
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '='
74
+ - !ruby/object:Gem::Version
75
+ version: 0.20.0
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '='
81
+ - !ruby/object:Gem::Version
82
+ version: 0.20.0
83
+ - !ruby/object:Gem::Dependency
84
+ name: colorize
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '='
88
+ - !ruby/object:Gem::Version
89
+ version: 0.8.1
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '='
95
+ - !ruby/object:Gem::Version
96
+ version: 0.8.1
97
+ - !ruby/object:Gem::Dependency
98
+ name: filecache
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '='
102
+ - !ruby/object:Gem::Version
103
+ version: 1.0.2
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '='
109
+ - !ruby/object:Gem::Version
110
+ version: 1.0.2
111
+ description: Ruby CLI client for typekit API
112
+ email:
113
+ - koushicbabuts@gmail.com
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - ".gitignore"
119
+ - ".rspec"
120
+ - ".travis.yml"
121
+ - Gemfile
122
+ - LICENSE.txt
123
+ - README.md
124
+ - Rakefile
125
+ - bin/typekit_client
126
+ - lib/typekit_client.rb
127
+ - lib/typekit_client/cli.rb
128
+ - lib/typekit_client/http_request.rb
129
+ - lib/typekit_client/typekit_api.rb
130
+ - lib/typekit_client/version.rb
131
+ - spec/http_request_spec.rb
132
+ - spec/spec_helper.rb
133
+ - spec/typekit_api_spec.rb
134
+ - spec/typekit_client_spec.rb
135
+ - typekit_client.gemspec
136
+ homepage: https://github.com/koushic88/typekit_client
137
+ licenses:
138
+ - MIT
139
+ metadata:
140
+ allowed_push_host: https://rubygems.org
141
+ post_install_message:
142
+ rdoc_options: []
143
+ require_paths:
144
+ - lib
145
+ required_ruby_version: !ruby/object:Gem::Requirement
146
+ requirements:
147
+ - - ">="
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
150
+ required_rubygems_version: !ruby/object:Gem::Requirement
151
+ requirements:
152
+ - - ">="
153
+ - !ruby/object:Gem::Version
154
+ version: '0'
155
+ requirements: []
156
+ rubyforge_project:
157
+ rubygems_version: 2.6.14
158
+ signing_key:
159
+ specification_version: 4
160
+ summary: Typekit Ruby Client
161
+ test_files: []