files.com 1.0.92

Sign up to get free protection for your applications and to get access to all the features.
Files changed (136) hide show
  1. checksums.yaml +7 -0
  2. data/CONTRIBUTORS +4 -0
  3. data/Gemfile +12 -0
  4. data/Gemfile.lock +82 -0
  5. data/LICENSE +21 -0
  6. data/README.md +119 -0
  7. data/Rakefile +12 -0
  8. data/SECURITY.md +24 -0
  9. data/_VERSION +1 -0
  10. data/bin/files +8 -0
  11. data/bin/files-console +16 -0
  12. data/docs/account_line_item.md +41 -0
  13. data/docs/action.md +37 -0
  14. data/docs/api_key.md +202 -0
  15. data/docs/app.md +59 -0
  16. data/docs/as2_key.md +133 -0
  17. data/docs/auto.md +11 -0
  18. data/docs/automation.md +190 -0
  19. data/docs/behavior.md +208 -0
  20. data/docs/bundle.md +252 -0
  21. data/docs/bundle_download.md +35 -0
  22. data/docs/clickwrap.md +143 -0
  23. data/docs/dns_record.md +35 -0
  24. data/docs/errors.md +17 -0
  25. data/docs/file.md +204 -0
  26. data/docs/file_action.md +126 -0
  27. data/docs/file_comment.md +116 -0
  28. data/docs/file_comment_reaction.md +62 -0
  29. data/docs/file_part_upload.md +37 -0
  30. data/docs/file_utils.md +4 -0
  31. data/docs/folder.md +90 -0
  32. data/docs/group.md +153 -0
  33. data/docs/group_user.md +124 -0
  34. data/docs/history.md +171 -0
  35. data/docs/history_export.md +174 -0
  36. data/docs/image.md +13 -0
  37. data/docs/invoice.md +72 -0
  38. data/docs/invoice_line_item.md +27 -0
  39. data/docs/ip_address.md +55 -0
  40. data/docs/lock.md +98 -0
  41. data/docs/message.md +147 -0
  42. data/docs/message_comment.md +132 -0
  43. data/docs/message_comment_reaction.md +94 -0
  44. data/docs/message_reaction.md +94 -0
  45. data/docs/notification.md +177 -0
  46. data/docs/payment.md +72 -0
  47. data/docs/payment_line_item.md +19 -0
  48. data/docs/permission.md +95 -0
  49. data/docs/preview.md +19 -0
  50. data/docs/project.md +121 -0
  51. data/docs/public_ip_address.md +13 -0
  52. data/docs/public_key.md +133 -0
  53. data/docs/remote_server.md +356 -0
  54. data/docs/request.md +100 -0
  55. data/docs/session.md +78 -0
  56. data/docs/site.md +448 -0
  57. data/docs/sso_strategy.md +114 -0
  58. data/docs/status.md +21 -0
  59. data/docs/style.md +93 -0
  60. data/docs/usage_daily_snapshot.md +45 -0
  61. data/docs/usage_snapshot.md +53 -0
  62. data/docs/user.md +535 -0
  63. data/docs/user_cipher_use.md +41 -0
  64. data/docs/user_request.md +93 -0
  65. data/files.com.gemspec +22 -0
  66. data/lib/files.com.rb +184 -0
  67. data/lib/files.com/api.rb +38 -0
  68. data/lib/files.com/api_client.rb +340 -0
  69. data/lib/files.com/errors.rb +41 -0
  70. data/lib/files.com/list.rb +95 -0
  71. data/lib/files.com/models/account_line_item.rb +82 -0
  72. data/lib/files.com/models/action.rb +77 -0
  73. data/lib/files.com/models/api_key.rb +270 -0
  74. data/lib/files.com/models/app.rb +106 -0
  75. data/lib/files.com/models/as2_key.rb +179 -0
  76. data/lib/files.com/models/auto.rb +17 -0
  77. data/lib/files.com/models/automation.rb +304 -0
  78. data/lib/files.com/models/behavior.rb +266 -0
  79. data/lib/files.com/models/bundle.rb +371 -0
  80. data/lib/files.com/models/bundle_download.rb +49 -0
  81. data/lib/files.com/models/clickwrap.rb +197 -0
  82. data/lib/files.com/models/dir.rb +3 -0
  83. data/lib/files.com/models/dns_record.rb +51 -0
  84. data/lib/files.com/models/errors.rb +22 -0
  85. data/lib/files.com/models/file.rb +968 -0
  86. data/lib/files.com/models/file_action.rb +126 -0
  87. data/lib/files.com/models/file_comment.rb +146 -0
  88. data/lib/files.com/models/file_comment_reaction.rb +100 -0
  89. data/lib/files.com/models/file_part_upload.rb +82 -0
  90. data/lib/files.com/models/file_utils.rb +118 -0
  91. data/lib/files.com/models/folder.rb +357 -0
  92. data/lib/files.com/models/group.rb +208 -0
  93. data/lib/files.com/models/group_user.rb +171 -0
  94. data/lib/files.com/models/history.rb +228 -0
  95. data/lib/files.com/models/history_export.rb +353 -0
  96. data/lib/files.com/models/image.rb +22 -0
  97. data/lib/files.com/models/invoice.rb +117 -0
  98. data/lib/files.com/models/invoice_line_item.rb +57 -0
  99. data/lib/files.com/models/ip_address.rb +66 -0
  100. data/lib/files.com/models/lock.rb +173 -0
  101. data/lib/files.com/models/message.rb +201 -0
  102. data/lib/files.com/models/message_comment.rb +165 -0
  103. data/lib/files.com/models/message_comment_reaction.rb +128 -0
  104. data/lib/files.com/models/message_reaction.rb +128 -0
  105. data/lib/files.com/models/notification.rb +263 -0
  106. data/lib/files.com/models/payment.rb +117 -0
  107. data/lib/files.com/models/payment_line_item.rb +37 -0
  108. data/lib/files.com/models/permission.rb +172 -0
  109. data/lib/files.com/models/preview.rb +37 -0
  110. data/lib/files.com/models/project.rb +140 -0
  111. data/lib/files.com/models/public_ip_address.rb +22 -0
  112. data/lib/files.com/models/public_key.rb +179 -0
  113. data/lib/files.com/models/remote_server.rb +680 -0
  114. data/lib/files.com/models/request.rb +179 -0
  115. data/lib/files.com/models/session.rb +247 -0
  116. data/lib/files.com/models/site.rb +733 -0
  117. data/lib/files.com/models/sso_strategy.rb +227 -0
  118. data/lib/files.com/models/status.rb +37 -0
  119. data/lib/files.com/models/style.rb +131 -0
  120. data/lib/files.com/models/usage_daily_snapshot.rb +66 -0
  121. data/lib/files.com/models/usage_snapshot.rb +96 -0
  122. data/lib/files.com/models/user.rb +876 -0
  123. data/lib/files.com/models/user_cipher_use.rb +63 -0
  124. data/lib/files.com/models/user_request.rb +127 -0
  125. data/lib/files.com/response.rb +25 -0
  126. data/lib/files.com/sizable_io.rb +32 -0
  127. data/lib/files.com/system_profiler.rb +56 -0
  128. data/lib/files.com/util.rb +106 -0
  129. data/lib/files.com/version.rb +5 -0
  130. data/spec/list_spec.rb +214 -0
  131. data/spec/models/file_spec.rb +68 -0
  132. data/spec/models/folder_spec.rb +40 -0
  133. data/spec/spec_helper.rb +36 -0
  134. data/test.sh +8 -0
  135. data/test/test.rb +75 -0
  136. metadata +235 -0
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Files
4
+ class UserCipherUse
5
+ attr_reader :options, :attributes
6
+
7
+ def initialize(attributes = {}, options = {})
8
+ @attributes = attributes || {}
9
+ @options = options || {}
10
+ end
11
+
12
+ # int64 - UserCipherUse ID
13
+ def id
14
+ @attributes[:id]
15
+ end
16
+
17
+ # string - The protocol and cipher employed
18
+ def protocol_cipher
19
+ @attributes[:protocol_cipher]
20
+ end
21
+
22
+ # date-time - The earliest recorded use of this combination of interface and protocol and cipher (for this user)
23
+ def created_at
24
+ @attributes[:created_at]
25
+ end
26
+
27
+ # string - The interface accessed
28
+ def interface
29
+ @attributes[:interface]
30
+ end
31
+
32
+ # date-time - The most recent use of this combination of interface and protocol and cipher (for this user)
33
+ def updated_at
34
+ @attributes[:updated_at]
35
+ end
36
+
37
+ # int64 - ID of the user who performed this access
38
+ def user_id
39
+ @attributes[:user_id]
40
+ end
41
+
42
+ # Parameters:
43
+ # user_id - int64 - User ID. Provide a value of `0` to operate the current session's user.
44
+ # page - int64 - Current page number.
45
+ # per_page - int64 - Number of records to show per page. (Max: 10,000, 1,000 or less is recommended).
46
+ # action - string - Deprecated: If set to `count` returns a count of matching records rather than the records themselves.
47
+ def self.list(params = {}, options = {})
48
+ raise InvalidParameterError.new("Bad parameter: user_id must be an Integer") if params.dig(:user_id) and !params.dig(:user_id).is_a?(Integer)
49
+ raise InvalidParameterError.new("Bad parameter: page must be an Integer") if params.dig(:page) and !params.dig(:page).is_a?(Integer)
50
+ raise InvalidParameterError.new("Bad parameter: per_page must be an Integer") if params.dig(:per_page) and !params.dig(:per_page).is_a?(Integer)
51
+ raise InvalidParameterError.new("Bad parameter: action must be an String") if params.dig(:action) and !params.dig(:action).is_a?(String)
52
+
53
+ response, options = Api.send_request("/user_cipher_uses", :get, params, options)
54
+ response.data.map do |entity_data|
55
+ UserCipherUse.new(entity_data, options)
56
+ end
57
+ end
58
+
59
+ def self.all(params = {}, options = {})
60
+ list(params, options)
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,127 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Files
4
+ class UserRequest
5
+ attr_reader :options, :attributes
6
+
7
+ def initialize(attributes = {}, options = {})
8
+ @attributes = attributes || {}
9
+ @options = options || {}
10
+ end
11
+
12
+ # string - User's full name
13
+ def name
14
+ @attributes[:name]
15
+ end
16
+
17
+ def name=(value)
18
+ @attributes[:name] = value
19
+ end
20
+
21
+ # email - User email address
22
+ def email
23
+ @attributes[:email]
24
+ end
25
+
26
+ def email=(value)
27
+ @attributes[:email] = value
28
+ end
29
+
30
+ # string - Details of the user's request
31
+ def details
32
+ @attributes[:details]
33
+ end
34
+
35
+ def details=(value)
36
+ @attributes[:details] = value
37
+ end
38
+
39
+ def delete(params = {})
40
+ params ||= {}
41
+ params[:id] = @attributes[:id]
42
+ raise MissingParameterError.new("Current object doesn't have a id") unless @attributes[:id]
43
+ raise InvalidParameterError.new("Bad parameter: id must be an Integer") if params.dig(:id) and !params.dig(:id).is_a?(Integer)
44
+ raise MissingParameterError.new("Parameter missing: id") unless params.dig(:id)
45
+
46
+ Api.send_request("/user_requests/#{@attributes[:id]}", :delete, params, @options)
47
+ end
48
+
49
+ def destroy(params = {})
50
+ delete(params)
51
+ end
52
+
53
+ def save
54
+ if @attributes[:id]
55
+ raise NotImplementedError.new("The UserRequest object doesn't support updates.")
56
+ else
57
+ new_obj = UserRequest.create(@attributes, @options)
58
+ @attributes = new_obj.attributes
59
+ end
60
+ end
61
+
62
+ # Parameters:
63
+ # page - int64 - Current page number.
64
+ # per_page - int64 - Number of records to show per page. (Max: 10,000, 1,000 or less is recommended).
65
+ # action - string - Deprecated: If set to `count` returns a count of matching records rather than the records themselves.
66
+ def self.list(params = {}, options = {})
67
+ raise InvalidParameterError.new("Bad parameter: page must be an Integer") if params.dig(:page) and !params.dig(:page).is_a?(Integer)
68
+ raise InvalidParameterError.new("Bad parameter: per_page must be an Integer") if params.dig(:per_page) and !params.dig(:per_page).is_a?(Integer)
69
+ raise InvalidParameterError.new("Bad parameter: action must be an String") if params.dig(:action) and !params.dig(:action).is_a?(String)
70
+
71
+ response, options = Api.send_request("/user_requests", :get, params, options)
72
+ response.data.map do |entity_data|
73
+ UserRequest.new(entity_data, options)
74
+ end
75
+ end
76
+
77
+ def self.all(params = {}, options = {})
78
+ list(params, options)
79
+ end
80
+
81
+ # Parameters:
82
+ # id (required) - int64 - User Request ID.
83
+ def self.find(id, params = {}, options = {})
84
+ params ||= {}
85
+ params[:id] = id
86
+ raise InvalidParameterError.new("Bad parameter: id must be an Integer") if params.dig(:id) and !params.dig(:id).is_a?(Integer)
87
+ raise MissingParameterError.new("Parameter missing: id") unless params.dig(:id)
88
+
89
+ response, options = Api.send_request("/user_requests/#{params[:id]}", :get, params, options)
90
+ UserRequest.new(response.data, options)
91
+ end
92
+
93
+ def self.get(id, params = {}, options = {})
94
+ find(id, params, options)
95
+ end
96
+
97
+ # Parameters:
98
+ # name (required) - string - Name of user requested
99
+ # email (required) - string - Email of user requested
100
+ # details (required) - string - Details of the user request
101
+ def self.create(params = {}, options = {})
102
+ raise InvalidParameterError.new("Bad parameter: name must be an String") if params.dig(:name) and !params.dig(:name).is_a?(String)
103
+ raise InvalidParameterError.new("Bad parameter: email must be an String") if params.dig(:email) and !params.dig(:email).is_a?(String)
104
+ raise InvalidParameterError.new("Bad parameter: details must be an String") if params.dig(:details) and !params.dig(:details).is_a?(String)
105
+ raise MissingParameterError.new("Parameter missing: name") unless params.dig(:name)
106
+ raise MissingParameterError.new("Parameter missing: email") unless params.dig(:email)
107
+ raise MissingParameterError.new("Parameter missing: details") unless params.dig(:details)
108
+
109
+ response, options = Api.send_request("/user_requests", :post, params, options)
110
+ UserRequest.new(response.data, options)
111
+ end
112
+
113
+ def self.delete(id, params = {}, options = {})
114
+ params ||= {}
115
+ params[:id] = id
116
+ raise InvalidParameterError.new("Bad parameter: id must be an Integer") if params.dig(:id) and !params.dig(:id).is_a?(Integer)
117
+ raise MissingParameterError.new("Parameter missing: id") unless params.dig(:id)
118
+
119
+ response, _options = Api.send_request("/user_requests/#{params[:id]}", :delete, params, options)
120
+ response.data
121
+ end
122
+
123
+ def self.destroy(id, params = {}, options = {})
124
+ delete(id, params, options)
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Files
4
+ class Response
5
+ attr_accessor :data, :http_body, :http_headers, :http_status
6
+
7
+ def self.from_faraday_hash(http_resp)
8
+ resp = new
9
+ resp.data = JSON.parse(http_resp[:body], symbolize_names: true) if http_resp[:status] != 204
10
+ resp.http_body = http_resp[:body]
11
+ resp.http_headers = http_resp[:headers]
12
+ resp.http_status = http_resp[:status]
13
+ resp
14
+ end
15
+
16
+ def self.from_faraday_response(http_resp)
17
+ resp = new
18
+ resp.data = JSON.parse(http_resp.body, symbolize_names: true) if http_resp.status != 204
19
+ resp.http_body = http_resp.body
20
+ resp.http_headers = http_resp.headers
21
+ resp.http_status = http_resp.status
22
+ resp
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,32 @@
1
+ module Files
2
+ class SizableIO < IO
3
+ def self.pipe
4
+ r, w = super
5
+
6
+ w.instance_variable_set(:@read_io, r)
7
+
8
+ [ r, w ]
9
+ end
10
+
11
+ def size
12
+ read_io.content_length_promise.wait.value
13
+ end
14
+
15
+ def fulfill_content_length(length)
16
+ read_io.content_length = length
17
+ read_io.content_length_promise.execute
18
+ end
19
+
20
+ protected
21
+
22
+ attr_accessor :content_length
23
+
24
+ def content_length_promise
25
+ @content_length_promise ||= Concurrent::Promise.new { content_length }
26
+ end
27
+
28
+ def read_io
29
+ @read_io || self
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Files
4
+ class SystemProfiler
5
+ def self.uname
6
+ if ::File.exist?("/proc/version")
7
+ ::File.read("/proc/version").strip
8
+ else
9
+ case RbConfig::CONFIG["host_os"]
10
+ when /linux|darwin|bsd|sunos|solaris|cygwin/i
11
+ uname_from_system
12
+ when /mswin|mingw/i
13
+ uname_from_system_ver
14
+ else
15
+ "unknown platform"
16
+ end
17
+ end
18
+ end
19
+
20
+ def self.uname_from_system
21
+ (`uname -a 2>/dev/null` || "").strip
22
+ rescue Errno::ENOENT
23
+ "uname executable not found"
24
+ rescue Errno::ENOMEM # couldn't create subprocess
25
+ "uname lookup failed"
26
+ end
27
+
28
+ def self.uname_from_system_ver
29
+ (`ver` || "").strip
30
+ rescue Errno::ENOENT
31
+ "ver executable not found"
32
+ rescue Errno::ENOMEM # couldn't create subprocess
33
+ "uname lookup failed"
34
+ end
35
+
36
+ def initialize
37
+ @uname = self.class.uname
38
+ end
39
+
40
+ def user_agent
41
+ lang_version = "#{RUBY_VERSION} p#{RUBY_PATCHLEVEL} (#{RUBY_RELEASE_DATE})"
42
+
43
+ {
44
+ application: Files.app_info,
45
+ bindings_version: Files::VERSION,
46
+ lang: "ruby",
47
+ lang_version: lang_version,
48
+ platform: RUBY_PLATFORM,
49
+ engine: defined?(RUBY_ENGINE) ? RUBY_ENGINE : "",
50
+ publisher: "Action Verb LLC",
51
+ uname: @uname,
52
+ hostname: Socket.gethostname,
53
+ }.delete_if { |_k, v| v.nil? }
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,106 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Files
4
+ module Util
5
+ OPTS = Set[:api_key, :client, :session_id].freeze
6
+ COLOR_CODES = {
7
+ black: 0, light_black: 60,
8
+ red: 1, light_red: 61,
9
+ green: 2, light_green: 62,
10
+ yellow: 3, light_yellow: 63,
11
+ blue: 4, light_blue: 64,
12
+ magenta: 5, light_magenta: 65,
13
+ cyan: 6, light_cyan: 66,
14
+ white: 7, light_white: 67,
15
+ default: 9,
16
+ }.freeze
17
+
18
+ def self.colorize(val, color, isatty)
19
+ return val unless isatty
20
+
21
+ mode = 0 # default
22
+ foreground = 30 + COLOR_CODES.fetch(color)
23
+ background = 40 + COLOR_CODES.fetch(:default)
24
+
25
+ "\033[#{mode};#{foreground};#{background}m#{val}\033[0m"
26
+ end
27
+
28
+ def self.level_name(level)
29
+ case level
30
+ when LEVEL_DEBUG then "debug"
31
+ when LEVEL_ERROR then "error"
32
+ when LEVEL_INFO then "info"
33
+ else level
34
+ end
35
+ end
36
+
37
+ def self.log_error(message, data = {})
38
+ if !Files.logger.nil? ||
39
+ !Files.log_level.nil? && Files.log_level <= Files::LEVEL_ERROR
40
+ log_internal(message, data, color: :cyan, level: Files::LEVEL_ERROR,
41
+ logger: Files.logger, out: $stderr
42
+ )
43
+ end
44
+ end
45
+
46
+ def self.log_info(message, data = {})
47
+ if !Files.logger.nil? ||
48
+ !Files.log_level.nil? && Files.log_level <= Files::LEVEL_INFO
49
+ log_internal(message, data, color: :cyan, level: Files::LEVEL_INFO,
50
+ logger: Files.logger, out: $stdout
51
+ )
52
+ end
53
+ end
54
+
55
+ def self.log_debug(message, data = {})
56
+ if !Files.logger.nil? ||
57
+ !Files.log_level.nil? && Files.log_level <= Files::LEVEL_DEBUG
58
+ log_internal(message, data, color: :blue, level: Files::LEVEL_DEBUG,
59
+ logger: Files.logger, out: $stdout
60
+ )
61
+ end
62
+ end
63
+
64
+ def self.log_internal(message, data = {}, color: nil, level: nil,
65
+ logger: nil, out: nil)
66
+ data_str = data.reject { |_k, v| v.nil? }
67
+ .map do |(k, v)|
68
+ format("%<key>s=%<value>s",
69
+ key: colorize(k, color, logger.nil? && !out.nil? && out.isatty),
70
+ value: v
71
+ )
72
+ end.join(" ")
73
+
74
+ if !logger.nil?
75
+ # the library's log levels are mapped to the same values as the
76
+ # standard library's logger
77
+ logger.log(level,
78
+ format("message=%<message>s %<data_str>s",
79
+ message: message,
80
+ data_str: data_str
81
+ )
82
+ )
83
+ elsif out.isatty
84
+ out.puts format("%<level>s %<message>s %<data_str>s",
85
+ level: colorize(level_name(level)[0, 4].upcase,
86
+ color, out.isatty
87
+ ),
88
+ message: message,
89
+ data_str: data_str
90
+ )
91
+ else
92
+ out.puts format("message=%<message>s level=%<level>s %<data_str>s",
93
+ message: message,
94
+ level: level_name(level),
95
+ data_str: data_str
96
+ )
97
+ end
98
+ end
99
+
100
+ def self.check_api_key!(key)
101
+ raise TypeError, "api_key must be a string" unless key.is_a?(String)
102
+
103
+ key
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Files
4
+ VERSION = "1.0"
5
+ end
@@ -0,0 +1,214 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe Files::List do
4
+ ResourceWrapper = Struct.new(:object, :options)
5
+ let(:options) { { client: client } }
6
+ let(:client) { instance_double(Files::ApiClient, cursor: nil) }
7
+ let(:params) { {} }
8
+
9
+ describe "#auto_paging_each" do
10
+ context "when per_page is set" do
11
+ let(:params) { { per_page: per_page } }
12
+ let(:per_page) { 3 }
13
+
14
+ context "when response includes a cursor" do
15
+ let(:client) { instance_double(Files::ApiClient) }
16
+ let(:stubbed_cursors) {
17
+ [
18
+ '3',
19
+ '6',
20
+ nil
21
+ ]
22
+ }
23
+
24
+ before do
25
+ allow(client).to receive(:cursor).and_return(*stubbed_cursors)
26
+ end
27
+
28
+ it "does not call the API until out of responses" do
29
+ server_results = ('a'..'h').to_a
30
+ times_block_yielded = 0
31
+ request_cursor = nil
32
+ response_cursor = nil
33
+
34
+ list = described_class.new(ResourceWrapper, params) {
35
+ times_block_yielded += 1
36
+ request_cursor = params[:cursor]
37
+ range_start = params[:cursor] ? params[:cursor].to_i : 0
38
+
39
+ response_data = server_results[range_start, per_page]
40
+ response_cursor = (range_start + per_page).to_s
41
+ [
42
+ instance_double(Files::Response, data: response_data, http_status: 200, http_headers: { "x-files-cursor" => response_cursor }),
43
+ options
44
+ ]
45
+ }
46
+ results = list.auto_paging_each
47
+ expect(results.class).to eq(Enumerator::Lazy)
48
+ expect(times_block_yielded).to eq(0)
49
+ expect(results.next.object).to eq('a')
50
+ expect(times_block_yielded).to eq(1)
51
+ expect(request_cursor).to eq(nil)
52
+ expect(results.next.object).to eq('b')
53
+ expect(results.next.object).to eq('c')
54
+ expect(results.next.object).to eq('d')
55
+ expect(times_block_yielded).to eq(2)
56
+ expect(request_cursor).to eq("3")
57
+ expect(results.next.object).to eq('e')
58
+ expect(results.next.object).to eq('f')
59
+ expect(results.next.object).to eq('g')
60
+ expect(results.next.object).to eq('h')
61
+ expect(times_block_yielded).to eq(3)
62
+ expect(request_cursor).to eq("6")
63
+ end
64
+
65
+ it "stops calling the API once there is an error" do
66
+ server_results = ('a'..'h').to_a
67
+ times_block_yielded = 0
68
+ list = described_class.new(ResourceWrapper, params) {
69
+ times_block_yielded += 1
70
+ [
71
+ instance_double(Files::Response, data: server_results.shift(per_page), http_status: 400),
72
+ options
73
+ ]
74
+ }
75
+ results = list.auto_paging_each
76
+ expect(results.count).to eq(0)
77
+ expect(times_block_yielded).to eq(1)
78
+ end
79
+ end
80
+
81
+ context "when response does not include a cursor" do
82
+ let(:client) { instance_double(Files::ApiClient, cursor: nil) }
83
+
84
+ it "stops requesting any more results after the first try" do
85
+ server_results = ('a'..'h').to_a
86
+ times_block_yielded = 0
87
+ list = described_class.new(ResourceWrapper, params) {
88
+ times_block_yielded += 1
89
+ [
90
+ instance_double(Files::Response, data: server_results.shift(per_page), http_status: 200),
91
+ options
92
+ ]
93
+ }
94
+ results = list.auto_paging_each
95
+ expect(results.count).to eq(3)
96
+ expect(times_block_yielded).to eq(1)
97
+ end
98
+ end
99
+ end
100
+
101
+ it "returns all results at once" do
102
+ server_results = ('a'..'h').to_a
103
+ times_block_yielded = 0
104
+ list = described_class.new(ResourceWrapper, params) {
105
+ times_block_yielded += 1
106
+ [
107
+ instance_double(Files::Response, data: server_results, http_status: 200),
108
+ options
109
+ ]
110
+ }
111
+ results = list.auto_paging_each
112
+ expect(results.count).to eq(8)
113
+ expect(times_block_yielded).to eq(1)
114
+ end
115
+ end
116
+
117
+ describe "#each" do
118
+ it "returns all results at once" do
119
+ server_results = ('a'..'h').to_a
120
+ times_block_yielded = 0
121
+ results = described_class.new(ResourceWrapper, params) {
122
+ times_block_yielded += 1
123
+ [
124
+ instance_double(Files::Response, data: server_results, http_status: 200),
125
+ options
126
+ ]
127
+ }
128
+ expect(results.count).to eq(8)
129
+ expect(times_block_yielded).to eq(1)
130
+ end
131
+
132
+ context "when per_page is set" do
133
+ let(:params) { { per_page: per_page } }
134
+ let(:per_page) { 3 }
135
+
136
+ context "when response includes a cursor" do
137
+ let(:client) { instance_double(Files::ApiClient, cursor: "XXX-XXX") }
138
+
139
+ it "does not call the API until out of responses" do
140
+ server_results = ('a'..'h').to_a
141
+ times_block_yielded = 0
142
+ list = described_class.new(ResourceWrapper, params) {
143
+ times_block_yielded += 1
144
+ [
145
+ instance_double(Files::Response, data: server_results.shift(per_page), http_status: 200),
146
+ options
147
+ ]
148
+ }
149
+ results = list.enum_for(:each)
150
+ expect(times_block_yielded).to eq(0)
151
+ expect(results.next.object).to eq('a')
152
+ expect(times_block_yielded).to eq(1)
153
+ expect(results.next.object).to eq('b')
154
+ expect(results.next.object).to eq('c')
155
+ next_results = list.next_page.enum_for(:each)
156
+ expect(times_block_yielded).to eq(2)
157
+ expect(next_results.next.object).to eq('d')
158
+ expect(next_results.next.object).to eq('e')
159
+ expect(next_results.next.object).to eq('f')
160
+ next_results = list.next_page.enum_for(:each)
161
+ expect(times_block_yielded).to eq(3)
162
+ expect(next_results.next.object).to eq('g')
163
+ expect(next_results.next.object).to eq('h')
164
+ next_results = list.next_page.enum_for(:each)
165
+ expect(next_results.count).to eq(0)
166
+ end
167
+
168
+ it "return the same data when call more than once" do
169
+ server_results = ('a'..'h').to_a
170
+ list = described_class.new(ResourceWrapper, params) {
171
+ [
172
+ instance_double(Files::Response, data: server_results.shift(per_page), http_status: 200),
173
+ options
174
+ ]
175
+ }
176
+ expect(list.to_a).to eq(list.to_a)
177
+ end
178
+
179
+ it "stops calling the API once there is an error" do
180
+ server_results = ('a'..'h').to_a
181
+ times_block_yielded = 0
182
+ results = described_class.new(ResourceWrapper, params) {
183
+ times_block_yielded += 1
184
+ [
185
+ instance_double(Files::Response, data: server_results, http_status: 400),
186
+ options
187
+ ]
188
+ }
189
+ expect(results.count).to eq(0)
190
+ expect(times_block_yielded).to eq(1)
191
+ end
192
+ end
193
+
194
+ context "when response does not include a cursor" do
195
+ let(:client) { instance_double(Files::ApiClient, cursor: nil) }
196
+
197
+ it "stops requesting any more results after the first try" do
198
+ server_results = ('a'..'h').to_a
199
+ times_block_yielded = 0
200
+ list = described_class.new(ResourceWrapper, params) {
201
+ times_block_yielded += 1
202
+ [
203
+ instance_double(Files::Response, data: server_results, http_status: 200),
204
+ options
205
+ ]
206
+ }
207
+ results = list.enum_for(:each)
208
+ expect(results.count).to eq(8)
209
+ expect(times_block_yielded).to eq(1)
210
+ end
211
+ end
212
+ end
213
+ end
214
+ end