typekit_client 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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: []