files.com 1.0.90

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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 +57 -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 +101 -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