cloudprint 0.3.2 → 0.3.3
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 +4 -4
- data/.gitignore +1 -0
- data/Gemfile +0 -3
- data/README.md +32 -62
- data/lib/cloudprint.rb +1 -0
- data/lib/cloudprint/auth.rb +35 -0
- data/lib/cloudprint/client.rb +15 -7
- data/lib/cloudprint/print_job_collection.rb +5 -3
- data/lib/cloudprint/printer.rb +8 -1
- data/lib/cloudprint/version.rb +1 -1
- data/test/auth_test.rb +49 -0
- data/test/connection_test.rb +1 -1
- data/test/helper.rb +6 -0
- data/test/print_job_test.rb +56 -7
- data/test/printer_test.rb +1 -2
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9941fa5e2ef6dad3668a1b587081fd47d8212624
|
4
|
+
data.tar.gz: 820a436e238805a68540c780d8b8aacba356218c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4697fc8d0a26b315eb253957ff2ed37ec63cbed534dbfd9e0e7829aa8665cd452a7ae3ba95952150fba5b481db75eeda24822527a201cd1e1812c3da9155cabb
|
7
|
+
data.tar.gz: aa1a0a977ba79526137a8690d5a8aa41ed98b46a5a405f2b4a6b258eda82c8f1e1350bcc099d73751fb7a8b2dcb480a4c6e315ca07206c54f8b3507f90f4635e
|
data/.gitignore
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,71 +1,50 @@
|
|
1
|
-
|
1
|
+
# Cloudprint [](https://travis-ci.org/thegengen/cloudprint)
|
2
2
|
|
3
|
-
Cloudprint is a Ruby library for interacting with Google's Cloud Print service,
|
4
|
-
a technology that allows you to print over the web from anywhere to any
|
5
|
-
printer.
|
3
|
+
Cloudprint is a Ruby library for interacting with Google's Cloud Print service, a technology that allows you to print over the web from anywhere to any printer.
|
6
4
|
|
7
|
-
|
8
|
-
To start using cloudprint, you first need to add it to your Gemfile, with an
|
9
|
-
entry such as this.
|
5
|
+
## Setting things up.
|
6
|
+
To start using cloudprint, you first need to add it to your Gemfile, with an entry such as this:
|
10
7
|
|
11
8
|
```ruby
|
12
9
|
gem 'cloudprint'
|
13
10
|
```
|
14
11
|
|
15
|
-
Afterwards, run
|
16
|
-
```
|
17
|
-
bundle
|
18
|
-
```
|
19
|
-
|
20
|
-
Next, you'll need to authenticate your users with Google Cloud Print. Cloud
|
21
|
-
Print uses OAuth2 as an authentication mechanism.
|
12
|
+
Afterwards, run `bundle install`
|
22
13
|
|
23
|
-
|
24
|
-
that, go to [https://cloud.google.com/console](https://cloud.google.com/console)
|
25
|
-
. Doing this will provide you with two things that will be needed to manage
|
26
|
-
your users' printers: a client ID and a client secret.
|
14
|
+
Next, you'll need to authenticate your users with Google Cloud Print. Cloud Print uses OAuth2 as an authentication mechanism.
|
27
15
|
|
28
|
-
|
29
|
-
Once you've registered your application, you will need to send your users to a
|
30
|
-
URL where they can allow your application to manage their printer.
|
16
|
+
First, you need to register your application within the Google Console. To do that, go to [https://cloud.google.com/console](https://cloud.google.com/console). Doing this will provide you with two things that will be needed to manage your users' printers: a client ID and a client secret.
|
31
17
|
|
32
|
-
|
33
|
-
|
18
|
+
## Authenticating your users.
|
19
|
+
Once you've registered your application, you will need to send your users to a URL where they can allow your application to manage their printer. You will also need to specify a URL *of yours* where they will be sent back after giving you access.
|
34
20
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
the Google Cloud Print interface.
|
21
|
+
```ruby
|
22
|
+
client = CloudPrint::Client.new(client_id: 'your_app_id', client_secret: 'your_app_secret')
|
23
|
+
redirect_url = 'http://your.app/redirect_uri'
|
24
|
+
client.auth.generate_url(redirect_url)
|
25
|
+
```
|
41
26
|
|
42
|
-
|
43
|
-
specify which will have an extra parameter named 'code' attached to it.
|
44
|
-
You then exchange this code for a refresh token.
|
45
|
-
Instructions on how to get a refresh token can be found here:
|
46
|
-
[https://developers.google.com/accounts/docs/OAuth2WebServer#handlingtheresponse](https://developers.google.com/accounts/docs/OAuth2WebServer#handlingtheresponse)
|
27
|
+
When they come, their request to your URL will have an extra parameter named 'code' attached to it. You then exchange this code for a refresh token. Note that you also have to include the redirect URL which you specified above.
|
47
28
|
|
48
|
-
|
49
|
-
|
29
|
+
```ruby
|
30
|
+
code = params[:code]
|
31
|
+
token = client.auth.generate_token(code, redirect_url)
|
32
|
+
```
|
50
33
|
|
51
|
-
|
52
|
-
First, you need to initialize a client with the data you just got from the
|
53
|
-
user. You will use this client object to interact with CloudPrint on behalf
|
54
|
-
of the user.
|
34
|
+
The client is all set to start using the URI, but you will want to store this refresh token so you can get access again at a later time. Subsequently, you can set the refresh token on `Cloudprint::Client` instances yourself.
|
55
35
|
|
56
36
|
```ruby
|
57
37
|
client = CloudPrint::Client.new(
|
58
38
|
refresh_token: 'refresh_token',
|
59
|
-
client_id: '
|
60
|
-
client_secret: '
|
61
|
-
callback_url: 'callback_url'
|
39
|
+
client_id: 'your_app_id',
|
40
|
+
client_secret: 'your_app_secret',
|
62
41
|
)
|
63
42
|
```
|
64
43
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
You then ask these objects to print things like this:
|
44
|
+
With this in place — and with the user's printer set up from the CloudPrint UI — you now have everything you need to start using their printer.
|
45
|
+
|
46
|
+
## Printing
|
47
|
+
Printing with the cloudprint gem is done with two kinds of objects. `CloudPrint::Printer` objects represent printers your users have set up in their CloudPrint accounts. You then ask these objects to print things like this:
|
69
48
|
|
70
49
|
```ruby
|
71
50
|
# Get a list of all the printers this client can talk to.
|
@@ -80,18 +59,11 @@ my_printer = client.printers.find('printer_id')
|
|
80
59
|
my_printer.print(content: "<h1>Hello World</h1>", content_type: "text/html")
|
81
60
|
```
|
82
61
|
|
83
|
-
Here's where the second kind of object comes in. If your content has been
|
84
|
-
succesfully sent to the printer, the cloudprint gem will return a
|
85
|
-
`CloudPrint::PrintJob` object. Among other things, this object will provide you
|
86
|
-
with an ID for the print job and, a status code, and an error code if anything
|
87
|
-
happened that prevented your document from getting printed.
|
62
|
+
Here's where the second kind of object comes in. If your content has been succesfully sent to the printer, the cloudprint gem will return a `CloudPrint::PrintJob` object. Among other things, this object will provide you with an ID for the print job and, a status code, and an error code if anything happened that prevented your document from getting printed.
|
88
63
|
|
89
|
-
Most of the time, the PrintJob object that your print() call will return has a
|
90
|
-
status of `IN_PROGRESS` or `QUEUED`.
|
64
|
+
Most of the time, the PrintJob object that your print() call will return has a status of `IN_PROGRESS` or `QUEUED`.
|
91
65
|
|
92
|
-
If your application can simply wait for the job, you can call refresh! on your
|
93
|
-
print job until its status changes. If not, you can store the ID and fetch the
|
94
|
-
print job at a later time to verify its status.
|
66
|
+
If your application can simply wait for the job, you can call refresh! on your print job until its status changes. If not, you can store the ID and fetch the print job at a later time to verify its status.
|
95
67
|
|
96
68
|
```ruby
|
97
69
|
my_job = client.print_jobs.find('job_id')
|
@@ -106,10 +78,8 @@ You can also delete a job, after it has finished.
|
|
106
78
|
my_job.delete!
|
107
79
|
```
|
108
80
|
|
109
|
-
|
110
|
-
For your testing needs, cloudprint objects can be stubbed at will and
|
111
|
-
initializing them does not require a connection. For example, to stub a print()
|
112
|
-
call with the shoulda library, one would do this:
|
81
|
+
## Testing
|
82
|
+
For your testing needs, cloudprint objects can be stubbed at will and initializing them does not require a connection. For example, to stub a print() call with the shoulda library, one would do this:
|
113
83
|
|
114
84
|
```ruby
|
115
85
|
my_printer = CloudPrint::Printer.new(id: 'id', status: 'OK', name: 'test_printer', display_name: 'Test Printer'
|
@@ -117,5 +87,5 @@ my_job = CloudPrint::PrintJob.new({}) # see the PrintJob class for what this has
|
|
117
87
|
my_printer.stubs(:print).returns(my_job)
|
118
88
|
```
|
119
89
|
|
120
|
-
|
90
|
+
## More help
|
121
91
|
Please submit an issue via GitHub if you need more help with the cloudprint gem.
|
data/lib/cloudprint.rb
CHANGED
@@ -0,0 +1,35 @@
|
|
1
|
+
require "uri"
|
2
|
+
|
3
|
+
module CloudPrint
|
4
|
+
class Auth
|
5
|
+
def initialize(client, options = {})
|
6
|
+
@client = client
|
7
|
+
@access_type = options[:access_type] || 'offline'
|
8
|
+
end
|
9
|
+
|
10
|
+
def generate_url(redirect_uri)
|
11
|
+
URI::HTTPS.build(
|
12
|
+
host: 'accounts.google.com',
|
13
|
+
path: '/o/oauth2/v2/auth',
|
14
|
+
query: URI.encode_www_form(url_params(redirect_uri))
|
15
|
+
).to_s
|
16
|
+
end
|
17
|
+
|
18
|
+
def generate_token(code, redirect_uri)
|
19
|
+
full_token = @client.oauth_client.auth_code.get_token(code, redirect_uri: redirect_uri)
|
20
|
+
@client.refresh_token = full_token.refresh_token
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def url_params(redirect_uri)
|
26
|
+
{
|
27
|
+
response_type: 'code',
|
28
|
+
scope: 'https://www.googleapis.com/auth/cloudprint',
|
29
|
+
client_id: @client.client_id,
|
30
|
+
access_type: @access_type,
|
31
|
+
redirect_uri: redirect_uri
|
32
|
+
}
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/cloudprint/client.rb
CHANGED
@@ -14,11 +14,16 @@ module CloudPrint
|
|
14
14
|
@client_id = options[:client_id]
|
15
15
|
@client_secret = options[:client_secret]
|
16
16
|
@callback_url = options[:callback_url]
|
17
|
+
@access_type = options[:access_type]
|
17
18
|
@connection = Connection.new(self)
|
18
19
|
@printers = PrinterCollection.new(self)
|
19
20
|
@print_jobs = PrintJobCollection.new(self)
|
20
21
|
end
|
21
22
|
|
23
|
+
def auth
|
24
|
+
@auth ||= CloudPrint::Auth.new(self, access_type: @access_type)
|
25
|
+
end
|
26
|
+
|
22
27
|
def access_token
|
23
28
|
(access_token_valid? && @access_token || renew_access_token!).token
|
24
29
|
end
|
@@ -32,18 +37,21 @@ module CloudPrint
|
|
32
37
|
@access_token.is_a?(OAuth2::AccessToken) && !@access_token.token.to_s.strip.empty? && !@access_token.expired?
|
33
38
|
end
|
34
39
|
|
40
|
+
def oauth_client
|
41
|
+
@oauth_client ||= OAuth2::Client.new(
|
42
|
+
client_id, client_secret,
|
43
|
+
:authorize_url => "/o/oauth2/auth",
|
44
|
+
:token_url => "/o/oauth2/token",
|
45
|
+
:access_token_url => "/o/oauth2/token",
|
46
|
+
:site => 'https://accounts.google.com/'
|
47
|
+
)
|
48
|
+
end
|
49
|
+
|
35
50
|
private
|
36
51
|
|
37
52
|
def renew_access_token!
|
38
53
|
@access_token = OAuth2::AccessToken.new(oauth_client, "", :refresh_token => refresh_token).refresh!
|
39
54
|
end
|
40
55
|
|
41
|
-
def oauth_client
|
42
|
-
@oauth_client ||= OAuth2::Client.new(client_id, client_secret,
|
43
|
-
:authorize_url => "/o/oauth2/auth",
|
44
|
-
:token_url => "/o/oauth2/token",
|
45
|
-
:access_token_url => "/o/oauth2/token",
|
46
|
-
:site => 'https://accounts.google.com/')
|
47
|
-
end
|
48
56
|
end
|
49
57
|
end
|
@@ -2,11 +2,11 @@ module CloudPrint
|
|
2
2
|
class PrintJobCollection
|
3
3
|
|
4
4
|
attr_accessor :client
|
5
|
-
|
5
|
+
|
6
6
|
def initialize client
|
7
7
|
@client = client
|
8
8
|
end
|
9
|
-
|
9
|
+
|
10
10
|
def find(jobid)
|
11
11
|
job = find_by_id(jobid)
|
12
12
|
return nil if job.nil?
|
@@ -26,7 +26,9 @@ module CloudPrint
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def find_by_id(id)
|
29
|
-
|
29
|
+
response = client.connection.post('/job', :jobid => id) || {}
|
30
|
+
return nil if response.nil? || response["job"].nil?
|
31
|
+
response["job"]
|
30
32
|
end
|
31
33
|
|
32
34
|
private
|
data/lib/cloudprint/printer.rb
CHANGED
@@ -20,7 +20,14 @@ module CloudPrint
|
|
20
20
|
def print(options)
|
21
21
|
content = options[:content]
|
22
22
|
method = content.is_a?(IO) || content.is_a?(StringIO) || content.is_a?(Tempfile) ? :multipart_post : :post
|
23
|
-
|
23
|
+
params = {
|
24
|
+
printerid: self.id,
|
25
|
+
title: options[:title],
|
26
|
+
content: options[:content],
|
27
|
+
contentType: options[:content_type]
|
28
|
+
}
|
29
|
+
params[:ticket] = options[:ticket].to_json if options[:ticket] && options[:ticket] != ''
|
30
|
+
response = client.connection.send(method, '/submit', params) || {}
|
24
31
|
return nil if response.nil? || response["job"].nil?
|
25
32
|
client.print_jobs.new_from_response response["job"]
|
26
33
|
end
|
data/lib/cloudprint/version.rb
CHANGED
data/test/auth_test.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class AuthTest < Minitest::Test
|
4
|
+
def setup
|
5
|
+
stub_access_token
|
6
|
+
@client = CloudPrint::Client.new(client_id: 'client_1234', client_secret: 'supersecret')
|
7
|
+
end
|
8
|
+
|
9
|
+
should 'generate a URI that points to accounts.google.com' do
|
10
|
+
assert_match 'accounts.google.com', generated_url
|
11
|
+
end
|
12
|
+
|
13
|
+
should 'generate a URI that asks for a code' do
|
14
|
+
assert_match 'response_type=code', generated_url
|
15
|
+
end
|
16
|
+
|
17
|
+
should 'generate a URI that asks for access to Cloudprint' do
|
18
|
+
assert_match '%2Fauth%2Fcloudprint', generated_url
|
19
|
+
end
|
20
|
+
|
21
|
+
should 'generate a URI that asks for offline access' do
|
22
|
+
assert_match 'access_type=offline', generated_url
|
23
|
+
end
|
24
|
+
|
25
|
+
should 'generate a URI that will redirect us to example.com' do
|
26
|
+
assert_match 'redirect_uri=http%3A%2F%2Fexample.com', generated_url
|
27
|
+
end
|
28
|
+
|
29
|
+
should 'generate a URI that contains the client_id' do
|
30
|
+
assert_match 'client_id=client_1234', generated_url
|
31
|
+
end
|
32
|
+
|
33
|
+
should 'generate a refresh token when passed in a code' do
|
34
|
+
mock_oauth_code = mock('oauth_code')
|
35
|
+
mock_oauth_code.stubs(:get_token).returns(mock_refresh_token)
|
36
|
+
|
37
|
+
@client.oauth_client.stubs(auth_code: mock_oauth_code)
|
38
|
+
token = @client.auth.generate_token('google_code', "http://example.com")
|
39
|
+
|
40
|
+
assert_equal "random_refresh_token", token
|
41
|
+
assert_equal "random_refresh_token", @client.refresh_token
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def generated_url
|
47
|
+
@client.auth.generate_url("http://example.com")
|
48
|
+
end
|
49
|
+
end
|
data/test/connection_test.rb
CHANGED
data/test/helper.rb
CHANGED
data/test/print_job_test.rb
CHANGED
@@ -7,24 +7,23 @@ class PrintJobTest < Minitest::Test
|
|
7
7
|
stub_connection
|
8
8
|
end
|
9
9
|
|
10
|
-
should
|
11
|
-
fake_connection.
|
10
|
+
should 'find a job' do
|
11
|
+
fake_connection.expects(:post).with('/job', {:jobid => "job_id"}).returns(real_job_hash)
|
12
12
|
assert @client.print_jobs.find('job_id').is_a?(CloudPrint::PrintJob)
|
13
13
|
end
|
14
14
|
|
15
15
|
should 'perform a remote request when finding a job' do
|
16
|
-
fake_connection.expects(:
|
17
|
-
|
16
|
+
fake_connection.expects(:post).with('/job', {:jobid => "job_id"}).returns(real_job_hash)
|
18
17
|
@client.print_jobs.find('job_id')
|
19
18
|
end
|
20
19
|
|
21
20
|
should 'gets the job details' do
|
22
|
-
fake_connection.
|
21
|
+
fake_connection.expects(:post).with('/job', {:jobid => "job_id"}).returns(real_job_hash)
|
23
22
|
job = @client.print_jobs.find('job_id')
|
24
23
|
|
25
24
|
assert_equal 'job_id', job.id
|
26
|
-
assert_equal '
|
27
|
-
assert_equal '
|
25
|
+
assert_equal 'mocked_status', job.status
|
26
|
+
assert_equal '', job.error_code
|
28
27
|
assert_equal 'printer_id', job.printer_id
|
29
28
|
assert_equal 'Job Title', job.title
|
30
29
|
assert_equal 'image/jpeg', job.content_type
|
@@ -154,4 +153,54 @@ class PrintJobTest < Minitest::Test
|
|
154
153
|
]
|
155
154
|
}
|
156
155
|
end
|
156
|
+
|
157
|
+
def real_job_hash
|
158
|
+
{
|
159
|
+
"success" => true,
|
160
|
+
"request" => {
|
161
|
+
"time" => "0",
|
162
|
+
"params" => {
|
163
|
+
"jobid" => [
|
164
|
+
"job_id"
|
165
|
+
]
|
166
|
+
},
|
167
|
+
"user" => "santa@claus.com",
|
168
|
+
"users" => [
|
169
|
+
"santa@claus.com"
|
170
|
+
]
|
171
|
+
},
|
172
|
+
"xsrf_token" => "AIp06DiNzjnfseYdqxujmG5P5oDpPh3N_A:1465433435813",
|
173
|
+
"job" => {
|
174
|
+
"ticketUrl" => "https://www.google.com/cloudprint/ticket?jobid=job_id",
|
175
|
+
"printerType" => "GOOGLE",
|
176
|
+
"printerName" => "Brother HL-L2380DW series",
|
177
|
+
"errorCode" => "",
|
178
|
+
"updateTime" => "1349722237676",
|
179
|
+
"title" => "Job Title",
|
180
|
+
"message" => "A message.",
|
181
|
+
"ownerId" => "santa@claus.com",
|
182
|
+
"tags" => [
|
183
|
+
"^own"
|
184
|
+
],
|
185
|
+
"uiState" => {
|
186
|
+
"summary" => "DONE"
|
187
|
+
},
|
188
|
+
"numberOfPages" => 1,
|
189
|
+
"createTime" => "1349722237676",
|
190
|
+
"semanticState" => {
|
191
|
+
"delivery_attempts" => 1,
|
192
|
+
"state" => {
|
193
|
+
"type" => "DONE"
|
194
|
+
},
|
195
|
+
"version" => "1.0"
|
196
|
+
},
|
197
|
+
"printerid" => "printer_id",
|
198
|
+
"fileUrl" => "https://www.google.com/cloudprint/download?id=job_id",
|
199
|
+
"id" => "job_id",
|
200
|
+
"rasterUrl" => "https://www.google.com/cloudprint/download?id\u003db8fa1266-625b-070c-5968-5039d2fdb982\u0026forcepwg\u003d1",
|
201
|
+
"contentType" => "image/jpeg",
|
202
|
+
"status" => "mocked_status"
|
203
|
+
}
|
204
|
+
}
|
205
|
+
end
|
157
206
|
end
|
data/test/printer_test.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require 'helper'
|
2
2
|
|
3
3
|
class PrinterTest < Minitest::Test
|
4
4
|
def setup
|
@@ -87,7 +87,6 @@ class PrinterTest < Minitest::Test
|
|
87
87
|
assert_nil job
|
88
88
|
end
|
89
89
|
|
90
|
-
|
91
90
|
should "print file" do
|
92
91
|
fake_connection.expects(:multipart_post).with('/submit', connection_print_file_params).returns(empty_job)
|
93
92
|
stub_connection
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cloudprint
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Eugen Minciu
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-06-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: oauth2
|
@@ -113,6 +113,7 @@ files:
|
|
113
113
|
- Rakefile
|
114
114
|
- cloudprint.gemspec
|
115
115
|
- lib/cloudprint.rb
|
116
|
+
- lib/cloudprint/auth.rb
|
116
117
|
- lib/cloudprint/client.rb
|
117
118
|
- lib/cloudprint/connection.rb
|
118
119
|
- lib/cloudprint/exceptions.rb
|
@@ -121,6 +122,7 @@ files:
|
|
121
122
|
- lib/cloudprint/printer.rb
|
122
123
|
- lib/cloudprint/printer_collection.rb
|
123
124
|
- lib/cloudprint/version.rb
|
125
|
+
- test/auth_test.rb
|
124
126
|
- test/cloudprint_test.rb
|
125
127
|
- test/connection_test.rb
|
126
128
|
- test/fixtures/ruby.png
|
@@ -147,11 +149,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
147
149
|
version: '0'
|
148
150
|
requirements: []
|
149
151
|
rubyforge_project: cloudprint
|
150
|
-
rubygems_version: 2.
|
152
|
+
rubygems_version: 2.6.11
|
151
153
|
signing_key:
|
152
154
|
specification_version: 4
|
153
155
|
summary: This library provides a Ruby interface to Google Cloud Print.
|
154
156
|
test_files:
|
157
|
+
- test/auth_test.rb
|
155
158
|
- test/cloudprint_test.rb
|
156
159
|
- test/connection_test.rb
|
157
160
|
- test/fixtures/ruby.png
|