nexus_mods 2.1.0 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -0
- data/lib/nexus_mods/api_client.rb +44 -3
- data/lib/nexus_mods/cacheable_with_expiry.rb +1 -1
- data/lib/nexus_mods/core_extensions/cacheable/cache_adapters/persistent_json_adapter.rb +2 -4
- data/lib/nexus_mods/version.rb +1 -1
- data/lib/nexus_mods.rb +114 -7
- data/spec/nexus_mods_test/factories/games.rb +10 -2
- data/spec/nexus_mods_test/factories/mod_files.rb +10 -2
- data/spec/nexus_mods_test/factories/mod_updates.rb +10 -2
- data/spec/nexus_mods_test/factories/mods.rb +10 -2
- data/spec/nexus_mods_test/scenarios/nexus_mods/nexus_mods_caching_spec.rb +261 -210
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0d5efb3b98f3d8b66565eff56b7b6360fc99bae69a256423e6eae391eb3cd676
|
|
4
|
+
data.tar.gz: 7091d96c8a79ec591e805bcc09958199187b5f0afd73de85b5da314c2e24381a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1485e5270d8fcffb7a2ebfec15848f0f2af3a2575beef6b2d1c4746af682bd13142d15f140adae1c9e7c15d731d85d63d01ec135f28600e73d58249bc130990e
|
|
7
|
+
data.tar.gz: eccb9f4312f63a8c8fc459592c4c0c618378f59a69a261512981e890c0bfffa8c2044bafbcd16da9ec9c8d3b980a53a2e5322a89c5eece959240cafb7ac05e19
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
# [v2.3.0](https://github.com/Muriel-Salvan/nexus_mods/compare/v2.2.0...v2.3.0) (2023-04-12 15:08:22)
|
|
2
|
+
|
|
3
|
+
### Features
|
|
4
|
+
|
|
5
|
+
* [[Feature] Add a way to set cache timestamps manually](https://github.com/Muriel-Salvan/nexus_mods/commit/7e5ac1d16d1d31f4aa33ebb9a748310e4572a06f)
|
|
6
|
+
|
|
7
|
+
# [v2.2.0](https://github.com/Muriel-Salvan/nexus_mods/compare/v2.1.0...v2.2.0) (2023-04-12 12:56:31)
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* [[Feature] Add possibility to retrieve the cache timestamp of API resources](https://github.com/Muriel-Salvan/nexus_mods/commit/ba67323a32472deb1f063a51683ff9282ef96981)
|
|
12
|
+
|
|
1
13
|
# [v2.1.0](https://github.com/Muriel-Salvan/nexus_mods/compare/v2.0.1...v2.1.0) (2023-04-11 18:24:04)
|
|
2
14
|
|
|
3
15
|
### Features
|
|
@@ -60,6 +60,37 @@ class NexusMods
|
|
|
60
60
|
cached_api(path, parameters:, verb:)
|
|
61
61
|
end
|
|
62
62
|
|
|
63
|
+
# Get the timestamp of the cached data linked to a given API call
|
|
64
|
+
#
|
|
65
|
+
# Parameters::
|
|
66
|
+
# * *path* (String): API path to contact (from v1/ and without .json)
|
|
67
|
+
# * *parameters* (Hash<Symbol,Object>): Optional parameters to add to the path [default: {}]
|
|
68
|
+
# * *verb* (Symbol): Verb to be used (:get, :post...) [default: :get]
|
|
69
|
+
# Result::
|
|
70
|
+
# * Time or nil: The refresh time of the data, or nil if not part of the cache
|
|
71
|
+
def api_cache_timestamp(path, parameters: {}, verb: :get)
|
|
72
|
+
key = ApiClient.cache_key(path, parameters:, verb:)
|
|
73
|
+
return unless Cacheable.cache_adapter.exist?(key)
|
|
74
|
+
|
|
75
|
+
str_time = Cacheable.cache_adapter.context.dig(key, 'invalidate_time')
|
|
76
|
+
str_time.nil? ? nil : Time.parse(str_time)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Set the timestamp of the cached data linked to a given API call.
|
|
80
|
+
# This should be used only to update the cache timestamp of a resource we know is still up-to-date without fetching the resource for real again.
|
|
81
|
+
#
|
|
82
|
+
# Parameters::
|
|
83
|
+
# * *path* (String): API path to contact (from v1/ and without .json)
|
|
84
|
+
# * *parameters* (Hash<Symbol,Object>): Optional parameters to add to the path [default: {}]
|
|
85
|
+
# * *verb* (Symbol): Verb to be used (:get, :post...) [default: :get]
|
|
86
|
+
# * *cache_timestamp* (Time): The cache timestamp to set for this resource
|
|
87
|
+
def set_api_cache_timestamp(path, cache_timestamp:, parameters: {}, verb: :get)
|
|
88
|
+
key = ApiClient.cache_key(path, parameters:, verb:)
|
|
89
|
+
Cacheable.cache_adapter.context[key] = {} unless Cacheable.cache_adapter.context.key?(key)
|
|
90
|
+
Cacheable.cache_adapter.context[key]['invalidate_time'] = cache_timestamp.utc.strftime('%FT%T.%9NUTC')
|
|
91
|
+
save_api_cache
|
|
92
|
+
end
|
|
93
|
+
|
|
63
94
|
# Send an HTTP request to the API and get back the HTTP response
|
|
64
95
|
#
|
|
65
96
|
# Parameters::
|
|
@@ -99,6 +130,18 @@ class NexusMods
|
|
|
99
130
|
# ApiClient: The API client to be used by the cacheable adapter (singleton pattern)
|
|
100
131
|
attr_accessor :api_client
|
|
101
132
|
|
|
133
|
+
# Get the cache key to be used for a given API query
|
|
134
|
+
#
|
|
135
|
+
# Parameters::
|
|
136
|
+
# * *path* (String): API path to contact (from v1/ and without .json)
|
|
137
|
+
# * *parameters* (Hash<Symbol,Object>): Optional parameters to add to the path [default: {}]
|
|
138
|
+
# * *verb* (Symbol): Verb to be used (:get, :post...) [default: :get]
|
|
139
|
+
# Result::
|
|
140
|
+
# * String: The corresponding cache key
|
|
141
|
+
def cache_key(path, parameters:, verb:)
|
|
142
|
+
"#{verb}/#{path}#{parameters.empty? ? '' : "/#{parameters.map { |param, value| "#{param}=#{value}" }.sort.join('/')}"}"
|
|
143
|
+
end
|
|
144
|
+
|
|
102
145
|
end
|
|
103
146
|
|
|
104
147
|
@api_client = nil
|
|
@@ -142,9 +185,7 @@ class NexusMods
|
|
|
142
185
|
cacheable_api(
|
|
143
186
|
:cached_api,
|
|
144
187
|
key_format: proc do |_target, _method_name, method_args, method_kwargs|
|
|
145
|
-
|
|
146
|
-
method_kwargs[:parameters].empty? ? '' : "/#{method_kwargs[:parameters].map { |param, value| "#{param}=#{value}" }.sort.join('/')}"
|
|
147
|
-
}"
|
|
188
|
+
cache_key(method_args.first, parameters: method_kwargs[:parameters], verb: method_kwargs[:verb])
|
|
148
189
|
end,
|
|
149
190
|
expiry_from_key: proc do |key|
|
|
150
191
|
# Example of keys:
|
|
@@ -45,7 +45,7 @@ class NexusMods
|
|
|
45
45
|
expiry_cache[key].nil? || (Time.now.utc - Time.parse(context['invalidate_time']).utc > expiry_cache[key])
|
|
46
46
|
end,
|
|
47
47
|
update_context_after_fetch: proc do |_key, _value, _options, context|
|
|
48
|
-
context['invalidate_time'] = Time.now.utc.strftime('%FT%
|
|
48
|
+
context['invalidate_time'] = Time.now.utc.strftime('%FT%T.%9NUTC')
|
|
49
49
|
end
|
|
50
50
|
}
|
|
51
51
|
)
|
|
@@ -13,6 +13,8 @@ module Cacheable
|
|
|
13
13
|
# * The context information is JSON serializable.
|
|
14
14
|
class PersistentJsonAdapter < MemoryAdapter
|
|
15
15
|
|
|
16
|
+
attr_reader :context
|
|
17
|
+
|
|
16
18
|
# Fetch a key with the givien cache options
|
|
17
19
|
#
|
|
18
20
|
# Parameters::
|
|
@@ -87,10 +89,6 @@ module Cacheable
|
|
|
87
89
|
@context = loaded_content['context']
|
|
88
90
|
end
|
|
89
91
|
|
|
90
|
-
private
|
|
91
|
-
|
|
92
|
-
attr_reader :context
|
|
93
|
-
|
|
94
92
|
end
|
|
95
93
|
|
|
96
94
|
end
|
data/lib/nexus_mods/version.rb
CHANGED
data/lib/nexus_mods.rb
CHANGED
|
@@ -143,6 +143,23 @@ class NexusMods
|
|
|
143
143
|
end
|
|
144
144
|
end
|
|
145
145
|
|
|
146
|
+
# Get the cached timestamp of the list of games
|
|
147
|
+
#
|
|
148
|
+
# Result::
|
|
149
|
+
# * Time or nil: Freshness time of the data in the API cache, or nil if not present in the cache
|
|
150
|
+
def games_cache_timestamp
|
|
151
|
+
@api_client.api_cache_timestamp('games')
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
# Set the cached timestamp of the list of games.
|
|
155
|
+
# This should be used only to update the cache timestamp of a resource we know is still up-to-date without fetching the resource for real again.
|
|
156
|
+
#
|
|
157
|
+
# Parameters::
|
|
158
|
+
# * *cache_timestamp* (Time): The cache timestamp to set for this resource
|
|
159
|
+
def set_games_cache_timestamp(cache_timestamp:)
|
|
160
|
+
@api_client.set_api_cache_timestamp('games', cache_timestamp:)
|
|
161
|
+
end
|
|
162
|
+
|
|
146
163
|
# Get information about a mod
|
|
147
164
|
#
|
|
148
165
|
# Parameters::
|
|
@@ -183,6 +200,28 @@ class NexusMods
|
|
|
183
200
|
)
|
|
184
201
|
end
|
|
185
202
|
|
|
203
|
+
# Get the cached timestamp of a mod information
|
|
204
|
+
#
|
|
205
|
+
# Parameters::
|
|
206
|
+
# * *game_domain_name* (String): Game domain name to query by default [default: @game_domain_name]
|
|
207
|
+
# * *mod_id* (Integer): The mod ID [default: @mod_id]
|
|
208
|
+
# Result::
|
|
209
|
+
# * Time or nil: Freshness time of the data in the API cache, or nil if not present in the cache
|
|
210
|
+
def mod_cache_timestamp(game_domain_name: @game_domain_name, mod_id: @mod_id)
|
|
211
|
+
@api_client.api_cache_timestamp("games/#{game_domain_name}/mods/#{mod_id}")
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
# Set the cached timestamp of a mod information.
|
|
215
|
+
# This should be used only to update the cache timestamp of a resource we know is still up-to-date without fetching the resource for real again.
|
|
216
|
+
#
|
|
217
|
+
# Parameters::
|
|
218
|
+
# * *game_domain_name* (String): Game domain name to query by default [default: @game_domain_name]
|
|
219
|
+
# * *mod_id* (Integer): The mod ID [default: @mod_id]
|
|
220
|
+
# * *cache_timestamp* (Time): The cache timestamp to set for this resource
|
|
221
|
+
def set_mod_cache_timestamp(cache_timestamp:, game_domain_name: @game_domain_name, mod_id: @mod_id)
|
|
222
|
+
@api_client.set_api_cache_timestamp("games/#{game_domain_name}/mods/#{mod_id}", cache_timestamp:)
|
|
223
|
+
end
|
|
224
|
+
|
|
186
225
|
# Get files belonging to a mod
|
|
187
226
|
#
|
|
188
227
|
# Parameters::
|
|
@@ -214,6 +253,28 @@ class NexusMods
|
|
|
214
253
|
end
|
|
215
254
|
end
|
|
216
255
|
|
|
256
|
+
# Get the cached timestamp of a mod files information
|
|
257
|
+
#
|
|
258
|
+
# Parameters::
|
|
259
|
+
# * *game_domain_name* (String): Game domain name to query by default [default: @game_domain_name]
|
|
260
|
+
# * *mod_id* (Integer): The mod ID [default: @mod_id]
|
|
261
|
+
# Result::
|
|
262
|
+
# * Time or nil: Freshness time of the data in the API cache, or nil if not present in the cache
|
|
263
|
+
def mod_files_cache_timestamp(game_domain_name: @game_domain_name, mod_id: @mod_id)
|
|
264
|
+
@api_client.api_cache_timestamp("games/#{game_domain_name}/mods/#{mod_id}/files")
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
# Set the cached timestamp of a mod files information.
|
|
268
|
+
# This should be used only to update the cache timestamp of a resource we know is still up-to-date without fetching the resource for real again.
|
|
269
|
+
#
|
|
270
|
+
# Parameters::
|
|
271
|
+
# * *game_domain_name* (String): Game domain name to query by default [default: @game_domain_name]
|
|
272
|
+
# * *mod_id* (Integer): The mod ID [default: @mod_id]
|
|
273
|
+
# * *cache_timestamp* (Time): The cache timestamp to set for this resource
|
|
274
|
+
def set_mod_files_cache_timestamp(cache_timestamp:, game_domain_name: @game_domain_name, mod_id: @mod_id)
|
|
275
|
+
@api_client.set_api_cache_timestamp("games/#{game_domain_name}/mods/#{mod_id}/files", cache_timestamp:)
|
|
276
|
+
end
|
|
277
|
+
|
|
217
278
|
# Get a list of updated mod ids since a given time
|
|
218
279
|
#
|
|
219
280
|
# Parameters::
|
|
@@ -227,6 +288,58 @@ class NexusMods
|
|
|
227
288
|
# Result::
|
|
228
289
|
# * Array<ModUpdates>: Mod's updates information
|
|
229
290
|
def updated_mods(game_domain_name: @game_domain_name, since: :one_day, clear_cache: false)
|
|
291
|
+
@api_client.api("games/#{game_domain_name}/mods/updated", parameters: period_to_url_params(since), clear_cache:).map do |updated_mod_json|
|
|
292
|
+
Api::ModUpdates.new(
|
|
293
|
+
mod_id: updated_mod_json['mod_id'],
|
|
294
|
+
latest_file_update: Time.at(updated_mod_json['latest_file_update']).utc,
|
|
295
|
+
latest_mod_activity: Time.at(updated_mod_json['latest_mod_activity']).utc
|
|
296
|
+
)
|
|
297
|
+
end
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
# Get the cached timestamp of updated mod ids
|
|
301
|
+
#
|
|
302
|
+
# Parameters::
|
|
303
|
+
# * *game_domain_name* (String): Game domain name to query by default [default: @game_domain_name]
|
|
304
|
+
# * *since* (Symbol): The time from which we look for updated mods [default: :one_day]
|
|
305
|
+
# Possible values are:
|
|
306
|
+
# * *one_day*: Since 1 day
|
|
307
|
+
# * *one_week*: Since 1 week
|
|
308
|
+
# * *one_month*: Since 1 month
|
|
309
|
+
# Result::
|
|
310
|
+
# * Time or nil: Freshness time of the data in the API cache, or nil if not present in the cache
|
|
311
|
+
def updated_mods_cache_timestamp(game_domain_name: @game_domain_name, since: :one_day)
|
|
312
|
+
@api_client.api_cache_timestamp("games/#{game_domain_name}/mods/updated", parameters: period_to_url_params(since))
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
# Set the cached timestamp of updated mod ids.
|
|
316
|
+
# This should be used only to update the cache timestamp of a resource we know is still up-to-date without fetching the resource for real again.
|
|
317
|
+
#
|
|
318
|
+
# Parameters::
|
|
319
|
+
# * *game_domain_name* (String): Game domain name to query by default [default: @game_domain_name]
|
|
320
|
+
# * *since* (Symbol): The time from which we look for updated mods [default: :one_day]
|
|
321
|
+
# Possible values are:
|
|
322
|
+
# * *one_day*: Since 1 day
|
|
323
|
+
# * *one_week*: Since 1 week
|
|
324
|
+
# * *one_month*: Since 1 month
|
|
325
|
+
# * *cache_timestamp* (Time): The cache timestamp to set for this resource
|
|
326
|
+
def set_updated_mods_cache_timestamp(cache_timestamp:, game_domain_name: @game_domain_name, since: :one_day)
|
|
327
|
+
@api_client.set_api_cache_timestamp("games/#{game_domain_name}/mods/updated", parameters: period_to_url_params(since), cache_timestamp:)
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
private
|
|
331
|
+
|
|
332
|
+
# Get the URL parameters from the required period
|
|
333
|
+
#
|
|
334
|
+
# Parameters::
|
|
335
|
+
# * *since* (Symbol): The time from which we look for updated mods
|
|
336
|
+
# Possible values are:
|
|
337
|
+
# * *one_day*: Since 1 day
|
|
338
|
+
# * *one_week*: Since 1 week
|
|
339
|
+
# * *one_month*: Since 1 month
|
|
340
|
+
# Result::
|
|
341
|
+
# * Hash<Symbol,Object>: Corresponding URL parameters
|
|
342
|
+
def period_to_url_params(since)
|
|
230
343
|
nexus_mods_period = {
|
|
231
344
|
one_day: '1d',
|
|
232
345
|
one_week: '1w',
|
|
@@ -234,13 +347,7 @@ class NexusMods
|
|
|
234
347
|
}[since]
|
|
235
348
|
raise "Unknown time stamp: #{since}" if nexus_mods_period.nil?
|
|
236
349
|
|
|
237
|
-
|
|
238
|
-
Api::ModUpdates.new(
|
|
239
|
-
mod_id: updated_mod_json['mod_id'],
|
|
240
|
-
latest_file_update: Time.at(updated_mod_json['latest_file_update']).utc,
|
|
241
|
-
latest_mod_activity: Time.at(updated_mod_json['latest_mod_activity']).utc
|
|
242
|
-
)
|
|
243
|
-
end
|
|
350
|
+
{ period: nexus_mods_period }
|
|
244
351
|
end
|
|
245
352
|
|
|
246
353
|
end
|
|
@@ -5,7 +5,7 @@ module NexusModsTest
|
|
|
5
5
|
module Games
|
|
6
6
|
|
|
7
7
|
# Test game with id 100
|
|
8
|
-
def json_game100
|
|
8
|
+
def self.json_game100
|
|
9
9
|
{
|
|
10
10
|
'id' => 100,
|
|
11
11
|
'name' => 'Morrowind',
|
|
@@ -35,8 +35,12 @@ module NexusModsTest
|
|
|
35
35
|
}
|
|
36
36
|
end
|
|
37
37
|
|
|
38
|
+
def json_game100
|
|
39
|
+
Games.json_game100
|
|
40
|
+
end
|
|
41
|
+
|
|
38
42
|
# Test game with id 101
|
|
39
|
-
def json_game101
|
|
43
|
+
def self.json_game101
|
|
40
44
|
{
|
|
41
45
|
'id' => 101,
|
|
42
46
|
'name' => 'Oblivion',
|
|
@@ -66,6 +70,10 @@ module NexusModsTest
|
|
|
66
70
|
}
|
|
67
71
|
end
|
|
68
72
|
|
|
73
|
+
def json_game101
|
|
74
|
+
Games.json_game101
|
|
75
|
+
end
|
|
76
|
+
|
|
69
77
|
# Expect a game to be the test game of id 100
|
|
70
78
|
#
|
|
71
79
|
# Parameters::
|
|
@@ -5,7 +5,7 @@ module NexusModsTest
|
|
|
5
5
|
module ModFiles
|
|
6
6
|
|
|
7
7
|
# Test mod file with id 2472
|
|
8
|
-
def json_mod_file2472
|
|
8
|
+
def self.json_mod_file2472
|
|
9
9
|
{
|
|
10
10
|
'id' => [
|
|
11
11
|
2472,
|
|
@@ -32,8 +32,12 @@ module NexusModsTest
|
|
|
32
32
|
}
|
|
33
33
|
end
|
|
34
34
|
|
|
35
|
+
def json_mod_file2472
|
|
36
|
+
ModFiles.json_mod_file2472
|
|
37
|
+
end
|
|
38
|
+
|
|
35
39
|
# Test mod file with id 2487
|
|
36
|
-
def json_mod_file2487
|
|
40
|
+
def self.json_mod_file2487
|
|
37
41
|
{
|
|
38
42
|
'id' => [
|
|
39
43
|
2487,
|
|
@@ -60,6 +64,10 @@ module NexusModsTest
|
|
|
60
64
|
}
|
|
61
65
|
end
|
|
62
66
|
|
|
67
|
+
def json_mod_file2487
|
|
68
|
+
ModFiles.json_mod_file2487
|
|
69
|
+
end
|
|
70
|
+
|
|
63
71
|
# Expect a mod's file to be the example one with id 2472
|
|
64
72
|
#
|
|
65
73
|
# Parameters::
|
|
@@ -5,7 +5,7 @@ module NexusModsTest
|
|
|
5
5
|
module ModUpdates
|
|
6
6
|
|
|
7
7
|
# Test mod updates with id 2014
|
|
8
|
-
def json_mod_updates2014
|
|
8
|
+
def self.json_mod_updates2014
|
|
9
9
|
{
|
|
10
10
|
'mod_id' => 2014,
|
|
11
11
|
'latest_file_update' => 1_655_813_855,
|
|
@@ -13,8 +13,12 @@ module NexusModsTest
|
|
|
13
13
|
}
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
+
def json_mod_updates2014
|
|
17
|
+
ModUpdates.json_mod_updates2014
|
|
18
|
+
end
|
|
19
|
+
|
|
16
20
|
# Test mod updates with id 100
|
|
17
|
-
def json_mod_updates100
|
|
21
|
+
def self.json_mod_updates100
|
|
18
22
|
{
|
|
19
23
|
'mod_id' => 100,
|
|
20
24
|
'latest_file_update' => 1_681_143_964,
|
|
@@ -22,6 +26,10 @@ module NexusModsTest
|
|
|
22
26
|
}
|
|
23
27
|
end
|
|
24
28
|
|
|
29
|
+
def json_mod_updates100
|
|
30
|
+
ModUpdates.json_mod_updates100
|
|
31
|
+
end
|
|
32
|
+
|
|
25
33
|
# Expect a mod's updates to be the example one with id 2014
|
|
26
34
|
#
|
|
27
35
|
# Parameters::
|
|
@@ -5,7 +5,7 @@ module NexusModsTest
|
|
|
5
5
|
module Mods
|
|
6
6
|
|
|
7
7
|
# Example of JSON object returned by the API for a mod information, having all possible fields
|
|
8
|
-
def json_complete_mod
|
|
8
|
+
def self.json_complete_mod
|
|
9
9
|
{
|
|
10
10
|
'name' => 'ApachiiSkyHair SSE',
|
|
11
11
|
'summary' => 'New Female and Male Hairstyles for Humans, Elves and Orcs. Converted hair from Sims2 and Sims3.<br />Standalone version.',
|
|
@@ -44,8 +44,12 @@ module NexusModsTest
|
|
|
44
44
|
}
|
|
45
45
|
end
|
|
46
46
|
|
|
47
|
+
def json_complete_mod
|
|
48
|
+
Mods.json_complete_mod
|
|
49
|
+
end
|
|
50
|
+
|
|
47
51
|
# Example of JSON object returned by the API for a mod information, having minimum fields
|
|
48
|
-
def json_partial_mod
|
|
52
|
+
def self.json_partial_mod
|
|
49
53
|
{
|
|
50
54
|
'mod_downloads' => 13_634_545,
|
|
51
55
|
'mod_unique_downloads' => 4_052_221,
|
|
@@ -75,6 +79,10 @@ module NexusModsTest
|
|
|
75
79
|
}
|
|
76
80
|
end
|
|
77
81
|
|
|
82
|
+
def json_partial_mod
|
|
83
|
+
Mods.json_partial_mod
|
|
84
|
+
end
|
|
85
|
+
|
|
78
86
|
# Expect a mod to be the example complete one
|
|
79
87
|
#
|
|
80
88
|
# Parameters::
|
|
@@ -10,163 +10,291 @@ describe NexusMods do
|
|
|
10
10
|
nexus_mods.api_limits
|
|
11
11
|
end
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
13
|
+
{
|
|
14
|
+
'games' => {
|
|
15
|
+
expected_api_path: '/v1/games.json',
|
|
16
|
+
mocked_api_json: [
|
|
17
|
+
NexusModsTest::Factories::Games.json_game100,
|
|
18
|
+
NexusModsTest::Factories::Games.json_game101
|
|
19
|
+
],
|
|
20
|
+
query: proc { |nm| nm.games },
|
|
21
|
+
query_without_cache: proc { |nm| nm.games(clear_cache: true) },
|
|
22
|
+
get_cache_timestamp: proc { |nm| nm.games_cache_timestamp },
|
|
23
|
+
set_cache_timestamp: proc { |nm, ts| nm.set_games_cache_timestamp(cache_timestamp: ts) },
|
|
24
|
+
expiry_cache_param: :games
|
|
25
|
+
},
|
|
26
|
+
'mods' => {
|
|
27
|
+
expected_api_path: '/v1/games/skyrimspecialedition/mods/2014.json',
|
|
28
|
+
mocked_api_json: NexusModsTest::Factories::Mods.json_complete_mod,
|
|
29
|
+
query: proc { |nm| nm.mod(game_domain_name: 'skyrimspecialedition', mod_id: 2014) },
|
|
30
|
+
query_without_cache: proc { |nm| nm.mod(game_domain_name: 'skyrimspecialedition', mod_id: 2014, clear_cache: true) },
|
|
31
|
+
get_cache_timestamp: proc { |nm| nm.mod_cache_timestamp(game_domain_name: 'skyrimspecialedition', mod_id: 2014) },
|
|
32
|
+
set_cache_timestamp: proc { |nm, ts| nm.set_mod_cache_timestamp(game_domain_name: 'skyrimspecialedition', mod_id: 2014, cache_timestamp: ts) },
|
|
33
|
+
expiry_cache_param: :mod
|
|
34
|
+
},
|
|
35
|
+
'mod files' => {
|
|
36
|
+
expected_api_path: '/v1/games/skyrimspecialedition/mods/2014/files.json',
|
|
37
|
+
mocked_api_json: {
|
|
38
|
+
files: [
|
|
39
|
+
NexusModsTest::Factories::ModFiles.json_mod_file2472,
|
|
40
|
+
NexusModsTest::Factories::ModFiles.json_mod_file2487
|
|
41
|
+
]
|
|
42
|
+
},
|
|
43
|
+
query: proc { |nm| nm.mod_files(game_domain_name: 'skyrimspecialedition', mod_id: 2014) },
|
|
44
|
+
query_without_cache: proc { |nm| nm.mod_files(game_domain_name: 'skyrimspecialedition', mod_id: 2014, clear_cache: true) },
|
|
45
|
+
get_cache_timestamp: proc { |nm| nm.mod_files_cache_timestamp(game_domain_name: 'skyrimspecialedition', mod_id: 2014) },
|
|
46
|
+
set_cache_timestamp: proc { |nm, ts| nm.set_mod_files_cache_timestamp(game_domain_name: 'skyrimspecialedition', mod_id: 2014, cache_timestamp: ts) },
|
|
47
|
+
expiry_cache_param: :mod_files
|
|
48
|
+
}
|
|
49
|
+
}.merge(
|
|
50
|
+
{
|
|
51
|
+
'last day' => {
|
|
52
|
+
since: :one_day,
|
|
53
|
+
expected_url_params: 'period=1d'
|
|
54
|
+
},
|
|
55
|
+
'last week' => {
|
|
56
|
+
since: :one_week,
|
|
57
|
+
expected_url_params: 'period=1w'
|
|
58
|
+
},
|
|
59
|
+
'last month' => {
|
|
60
|
+
since: :one_month,
|
|
61
|
+
expected_url_params: 'period=1m'
|
|
62
|
+
}
|
|
63
|
+
}.to_h do |since, since_config|
|
|
64
|
+
[
|
|
65
|
+
"mod updates since #{since}",
|
|
66
|
+
{
|
|
67
|
+
expected_api_path: "/v1/games/skyrimspecialedition/mods/updated.json?#{since_config[:expected_url_params]}",
|
|
68
|
+
mocked_api_json: [
|
|
69
|
+
NexusModsTest::Factories::ModUpdates.json_mod_updates2014,
|
|
70
|
+
NexusModsTest::Factories::ModUpdates.json_mod_updates100
|
|
71
|
+
],
|
|
72
|
+
query: proc { |nm| nm.updated_mods(game_domain_name: 'skyrimspecialedition', since: since_config[:since]) },
|
|
73
|
+
query_without_cache: proc { |nm| nm.updated_mods(game_domain_name: 'skyrimspecialedition', since: since_config[:since], clear_cache: true) },
|
|
74
|
+
get_cache_timestamp: proc { |nm| nm.updated_mods_cache_timestamp(game_domain_name: 'skyrimspecialedition', since: since_config[:since]) },
|
|
75
|
+
set_cache_timestamp: proc { |nm, ts| nm.set_updated_mods_cache_timestamp(game_domain_name: 'skyrimspecialedition', since: since_config[:since], cache_timestamp: ts) }
|
|
76
|
+
}
|
|
20
77
|
]
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
expect(nexus_mods.games).to eq games
|
|
24
|
-
end
|
|
78
|
+
end
|
|
79
|
+
).each do |resource, resource_config|
|
|
25
80
|
|
|
26
|
-
|
|
27
|
-
expect_validate_user
|
|
28
|
-
expect_http_call_to(
|
|
29
|
-
path: '/v1/games.json',
|
|
30
|
-
json: [
|
|
31
|
-
json_game100,
|
|
32
|
-
json_game101
|
|
33
|
-
],
|
|
34
|
-
times: 2
|
|
35
|
-
)
|
|
36
|
-
games = nexus_mods.games
|
|
37
|
-
expect(nexus_mods.games(clear_cache: true)).to eq games
|
|
38
|
-
end
|
|
81
|
+
context "when testing #{resource}" do
|
|
39
82
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
83
|
+
it 'caches API queries' do
|
|
84
|
+
expect_validate_user
|
|
85
|
+
expect_http_call_to(
|
|
86
|
+
path: resource_config[:expected_api_path],
|
|
87
|
+
json: resource_config[:mocked_api_json]
|
|
88
|
+
)
|
|
89
|
+
resource = resource_config[:query].call(nexus_mods)
|
|
90
|
+
expect(resource_config[:query].call(nexus_mods)).to eq resource
|
|
91
|
+
end
|
|
49
92
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
93
|
+
it 'does not cache API queries if asked' do
|
|
94
|
+
expect_validate_user
|
|
95
|
+
expect_http_call_to(
|
|
96
|
+
path: resource_config[:expected_api_path],
|
|
97
|
+
json: resource_config[:mocked_api_json],
|
|
98
|
+
times: 2
|
|
99
|
+
)
|
|
100
|
+
resource = resource_config[:query].call(nexus_mods)
|
|
101
|
+
expect(resource_config[:query_without_cache].call(nexus_mods)).to eq resource
|
|
102
|
+
end
|
|
60
103
|
|
|
61
|
-
|
|
62
|
-
expect_validate_user
|
|
63
|
-
expect_http_call_to(
|
|
64
|
-
path: '/v1/games/skyrimspecialedition/mods/2014/files.json',
|
|
65
|
-
json: { files: [json_mod_file2472, json_mod_file2487] }
|
|
66
|
-
)
|
|
67
|
-
mod_files = nexus_mods.mod_files(game_domain_name: 'skyrimspecialedition', mod_id: 2014)
|
|
68
|
-
expect(nexus_mods.mod_files(game_domain_name: 'skyrimspecialedition', mod_id: 2014)).to eq mod_files
|
|
69
|
-
end
|
|
104
|
+
if resource_config[:expiry_cache_param]
|
|
70
105
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
106
|
+
it 'expires API queries cache' do
|
|
107
|
+
expect_validate_user
|
|
108
|
+
expect_http_call_to(
|
|
109
|
+
path: resource_config[:expected_api_path],
|
|
110
|
+
json: resource_config[:mocked_api_json],
|
|
111
|
+
times: 2
|
|
112
|
+
)
|
|
113
|
+
nexus_mods_instance = nexus_mods(api_cache_expiry: { resource_config[:expiry_cache_param] => 1 })
|
|
114
|
+
resource = resource_config[:query].call(nexus_mods_instance)
|
|
115
|
+
sleep 2
|
|
116
|
+
expect(resource_config[:query].call(nexus_mods_instance)).to eq resource
|
|
117
|
+
end
|
|
81
118
|
|
|
82
|
-
|
|
83
|
-
'last day' => {
|
|
84
|
-
since: :one_day,
|
|
85
|
-
expected_url_params: 'period=1d'
|
|
86
|
-
},
|
|
87
|
-
'last week' => {
|
|
88
|
-
since: :one_week,
|
|
89
|
-
expected_url_params: 'period=1w'
|
|
90
|
-
},
|
|
91
|
-
'last month' => {
|
|
92
|
-
since: :one_month,
|
|
93
|
-
expected_url_params: 'period=1m'
|
|
94
|
-
}
|
|
95
|
-
}.each do |since, since_config|
|
|
119
|
+
end
|
|
96
120
|
|
|
97
|
-
|
|
121
|
+
it 'stores no timestamp of the data stored in the API cache before fetching data' do
|
|
122
|
+
expect_validate_user
|
|
123
|
+
expect(resource_config[:get_cache_timestamp].call(nexus_mods)).to be_nil
|
|
124
|
+
end
|
|
98
125
|
|
|
99
|
-
it '
|
|
126
|
+
it 'retrieves the timestamp of the data stored in the API cache' do
|
|
100
127
|
expect_validate_user
|
|
101
128
|
expect_http_call_to(
|
|
102
|
-
path:
|
|
103
|
-
json: [
|
|
104
|
-
json_mod_updates2014,
|
|
105
|
-
json_mod_updates100
|
|
106
|
-
]
|
|
129
|
+
path: resource_config[:expected_api_path],
|
|
130
|
+
json: resource_config[:mocked_api_json]
|
|
107
131
|
)
|
|
108
|
-
|
|
109
|
-
|
|
132
|
+
before = Time.now
|
|
133
|
+
resource_config[:query].call(nexus_mods)
|
|
134
|
+
after = Time.now
|
|
135
|
+
expect(resource_config[:get_cache_timestamp].call(nexus_mods)).to be_between(before, after)
|
|
110
136
|
end
|
|
111
137
|
|
|
112
|
-
it '
|
|
138
|
+
it 'changes manually the timestamp of the data stored in the API cache' do
|
|
113
139
|
expect_validate_user
|
|
114
140
|
expect_http_call_to(
|
|
115
|
-
path:
|
|
116
|
-
json: [
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
141
|
+
path: resource_config[:expected_api_path],
|
|
142
|
+
json: resource_config[:mocked_api_json]
|
|
143
|
+
)
|
|
144
|
+
resource_config[:query].call(nexus_mods)
|
|
145
|
+
new_cache_timestamp = Time.parse('2023-01-12 11:22:33 UTC')
|
|
146
|
+
resource_config[:set_cache_timestamp].call(nexus_mods, new_cache_timestamp)
|
|
147
|
+
expect(resource_config[:get_cache_timestamp].call(nexus_mods)).to eq new_cache_timestamp
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
it 'retrieves the timestamp of the games data stored in the cache even after cache is used' do
|
|
151
|
+
expect_validate_user
|
|
152
|
+
expect_http_call_to(
|
|
153
|
+
path: resource_config[:expected_api_path],
|
|
154
|
+
json: resource_config[:mocked_api_json]
|
|
155
|
+
)
|
|
156
|
+
before = Time.now
|
|
157
|
+
resource_config[:query].call(nexus_mods)
|
|
158
|
+
after = Time.now
|
|
159
|
+
resource_config[:query].call(nexus_mods)
|
|
160
|
+
expect(resource_config[:get_cache_timestamp].call(nexus_mods)).to be_between(before, after)
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
it 'retrieves the timestamp of the games data stored in the cache even after cache is persisted' do
|
|
164
|
+
with_api_cache_file do |api_cache_file|
|
|
165
|
+
expect_validate_user(times: 2)
|
|
166
|
+
expect_http_call_to(
|
|
167
|
+
path: resource_config[:expected_api_path],
|
|
168
|
+
json: resource_config[:mocked_api_json]
|
|
169
|
+
)
|
|
170
|
+
before = Time.now
|
|
171
|
+
resource_config[:query].call(nexus_mods(api_cache_file:))
|
|
172
|
+
after = Time.now
|
|
173
|
+
reset_nexus_mods
|
|
174
|
+
expect(resource_config[:get_cache_timestamp].call(nexus_mods(api_cache_file:))).to be_between(before, after)
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
it 'persists the cache timestamp that has been changed manually' do
|
|
179
|
+
with_api_cache_file do |api_cache_file|
|
|
180
|
+
expect_validate_user(times: 2)
|
|
181
|
+
expect_http_call_to(
|
|
182
|
+
path: resource_config[:expected_api_path],
|
|
183
|
+
json: resource_config[:mocked_api_json]
|
|
184
|
+
)
|
|
185
|
+
resource_config[:query].call(nexus_mods(api_cache_file:))
|
|
186
|
+
new_cache_timestamp = Time.parse('2023-01-12 11:22:33 UTC')
|
|
187
|
+
resource_config[:set_cache_timestamp].call(nexus_mods, new_cache_timestamp)
|
|
188
|
+
reset_nexus_mods
|
|
189
|
+
expect(resource_config[:get_cache_timestamp].call(nexus_mods(api_cache_file:))).to eq new_cache_timestamp
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
it 'updates the timestamp of the data stored in the API cache by forcing an API query' do
|
|
194
|
+
expect_validate_user
|
|
195
|
+
expect_http_call_to(
|
|
196
|
+
path: resource_config[:expected_api_path],
|
|
197
|
+
json: resource_config[:mocked_api_json],
|
|
120
198
|
times: 2
|
|
121
199
|
)
|
|
122
|
-
|
|
123
|
-
|
|
200
|
+
resource_config[:query].call(nexus_mods)
|
|
201
|
+
sleep 1
|
|
202
|
+
before = Time.now
|
|
203
|
+
resource_config[:query_without_cache].call(nexus_mods)
|
|
204
|
+
after = Time.now
|
|
205
|
+
expect(resource_config[:get_cache_timestamp].call(nexus_mods)).to be_between(before, after)
|
|
124
206
|
end
|
|
125
207
|
|
|
126
|
-
|
|
208
|
+
it 'updates the timestamp of the data stored in the API cache by updating manually the cache timestamp' do
|
|
209
|
+
expect_validate_user
|
|
210
|
+
expect_http_call_to(
|
|
211
|
+
path: resource_config[:expected_api_path],
|
|
212
|
+
json: resource_config[:mocked_api_json],
|
|
213
|
+
times: 2
|
|
214
|
+
)
|
|
215
|
+
resource_config[:query].call(nexus_mods)
|
|
216
|
+
resource_config[:set_cache_timestamp].call(nexus_mods, Time.now.utc - (365 * 24 * 60 * 60))
|
|
217
|
+
before = Time.now
|
|
218
|
+
resource_config[:query].call(nexus_mods)
|
|
219
|
+
after = Time.now
|
|
220
|
+
expect(resource_config[:get_cache_timestamp].call(nexus_mods)).to be_between(before, after)
|
|
221
|
+
end
|
|
127
222
|
|
|
128
|
-
|
|
223
|
+
context 'when testing cache persistence in files' do
|
|
129
224
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
sleep 2
|
|
143
|
-
expect(nexus_mods_instance.games).to eq games
|
|
144
|
-
end
|
|
225
|
+
it 'persists API cache in a file' do
|
|
226
|
+
with_api_cache_file do |api_cache_file|
|
|
227
|
+
expect_validate_user
|
|
228
|
+
expect_http_call_to(
|
|
229
|
+
path: resource_config[:expected_api_path],
|
|
230
|
+
json: resource_config[:mocked_api_json]
|
|
231
|
+
)
|
|
232
|
+
resource_config[:query].call(nexus_mods(api_cache_file:))
|
|
233
|
+
expect(File.exist?(api_cache_file)).to be true
|
|
234
|
+
expect(File.size(api_cache_file)).to be > 0
|
|
235
|
+
end
|
|
236
|
+
end
|
|
145
237
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
238
|
+
it 'uses API cache from a file' do
|
|
239
|
+
with_api_cache_file do |api_cache_file|
|
|
240
|
+
expect_validate_user(times: 2)
|
|
241
|
+
expect_http_call_to(
|
|
242
|
+
path: resource_config[:expected_api_path],
|
|
243
|
+
json: resource_config[:mocked_api_json]
|
|
244
|
+
)
|
|
245
|
+
# Generate the cache first
|
|
246
|
+
resource = resource_config[:query].call(nexus_mods(api_cache_file:))
|
|
247
|
+
# Force a new instance of NexusMods API to run
|
|
248
|
+
reset_nexus_mods
|
|
249
|
+
expect(resource_config[:query].call(nexus_mods(api_cache_file:))).to eq resource
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
if resource_config[:expiry_cache_param]
|
|
254
|
+
|
|
255
|
+
it 'uses API cache from a file, taking expiry time into account' do
|
|
256
|
+
with_api_cache_file do |api_cache_file|
|
|
257
|
+
expect_validate_user(times: 2)
|
|
258
|
+
expect_http_call_to(
|
|
259
|
+
path: resource_config[:expected_api_path],
|
|
260
|
+
json: resource_config[:mocked_api_json],
|
|
261
|
+
times: 2
|
|
262
|
+
)
|
|
263
|
+
# Generate the cache first
|
|
264
|
+
resource = resource_config[:query].call(nexus_mods(api_cache_file:, api_cache_expiry: { resource_config[:expiry_cache_param] => 1 }))
|
|
265
|
+
# Force a new instance of NexusMods API to run
|
|
266
|
+
reset_nexus_mods
|
|
267
|
+
sleep 2
|
|
268
|
+
# As the expiry time is 1 second, then the cache should still be invalidated
|
|
269
|
+
expect(resource_config[:query].call(nexus_mods(api_cache_file:, api_cache_expiry: { resource_config[:expiry_cache_param] => 1 }))).to eq resource
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
it 'uses API cache from a file, taking expiry time of the new process into account' do
|
|
274
|
+
with_api_cache_file do |api_cache_file|
|
|
275
|
+
expect_validate_user(times: 2)
|
|
276
|
+
expect_http_call_to(
|
|
277
|
+
path: resource_config[:expected_api_path],
|
|
278
|
+
json: resource_config[:mocked_api_json],
|
|
279
|
+
times: 2
|
|
280
|
+
)
|
|
281
|
+
# Generate the cache first
|
|
282
|
+
resource = resource_config[:query].call(nexus_mods(api_cache_file:, api_cache_expiry: { resource_config[:expiry_cache_param] => 10 }))
|
|
283
|
+
# Force a new instance of NexusMods API to run
|
|
284
|
+
reset_nexus_mods
|
|
285
|
+
sleep 2
|
|
286
|
+
# Even if the expiry time was 10 seconds while fetching the resource,
|
|
287
|
+
# if we decide it has to be 1 second now then it has to be invalidated.
|
|
288
|
+
expect(resource_config[:query].call(nexus_mods(api_cache_file:, api_cache_expiry: { resource_config[:expiry_cache_param] => 1 }))).to eq resource
|
|
289
|
+
end
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
end
|
|
158
297
|
|
|
159
|
-
it 'expires mod files queries cache' do
|
|
160
|
-
expect_validate_user
|
|
161
|
-
expect_http_call_to(
|
|
162
|
-
path: '/v1/games/skyrimspecialedition/mods/2014/files.json',
|
|
163
|
-
json: { files: [json_mod_file2472, json_mod_file2487] },
|
|
164
|
-
times: 2
|
|
165
|
-
)
|
|
166
|
-
nexus_mods_instance = nexus_mods(api_cache_expiry: { mod_files: 1 })
|
|
167
|
-
mod_files = nexus_mods_instance.mod_files(game_domain_name: 'skyrimspecialedition', mod_id: 2014)
|
|
168
|
-
sleep 2
|
|
169
|
-
expect(nexus_mods_instance.mod_files(game_domain_name: 'skyrimspecialedition', mod_id: 2014)).to eq mod_files
|
|
170
298
|
end
|
|
171
299
|
|
|
172
300
|
it 'only clears the cache of the wanted resource' do
|
|
@@ -190,83 +318,6 @@ describe NexusMods do
|
|
|
190
318
|
|
|
191
319
|
context 'with file persistence' do
|
|
192
320
|
|
|
193
|
-
it 'persists API cache in a file' do
|
|
194
|
-
with_api_cache_file do |api_cache_file|
|
|
195
|
-
expect_validate_user
|
|
196
|
-
expect_http_call_to(
|
|
197
|
-
path: '/v1/games.json',
|
|
198
|
-
json: [
|
|
199
|
-
json_game100,
|
|
200
|
-
json_game101
|
|
201
|
-
]
|
|
202
|
-
)
|
|
203
|
-
nexus_mods(api_cache_file:).games
|
|
204
|
-
expect(File.exist?(api_cache_file)).to be true
|
|
205
|
-
expect(File.size(api_cache_file)).to be > 0
|
|
206
|
-
end
|
|
207
|
-
end
|
|
208
|
-
|
|
209
|
-
it 'uses API cache from a file' do
|
|
210
|
-
with_api_cache_file do |api_cache_file|
|
|
211
|
-
expect_validate_user(times: 2)
|
|
212
|
-
expect_http_call_to(
|
|
213
|
-
path: '/v1/games.json',
|
|
214
|
-
json: [
|
|
215
|
-
json_game100,
|
|
216
|
-
json_game101
|
|
217
|
-
]
|
|
218
|
-
)
|
|
219
|
-
# Generate the cache first
|
|
220
|
-
games = nexus_mods(api_cache_file:).games
|
|
221
|
-
# Force a new instance of NexusMods API to run
|
|
222
|
-
reset_nexus_mods
|
|
223
|
-
expect(nexus_mods(api_cache_file:).games).to eq games
|
|
224
|
-
end
|
|
225
|
-
end
|
|
226
|
-
|
|
227
|
-
it 'uses API cache from a file, taking expiry time into account' do
|
|
228
|
-
with_api_cache_file do |api_cache_file|
|
|
229
|
-
expect_validate_user(times: 2)
|
|
230
|
-
expect_http_call_to(
|
|
231
|
-
path: '/v1/games.json',
|
|
232
|
-
json: [
|
|
233
|
-
json_game100,
|
|
234
|
-
json_game101
|
|
235
|
-
],
|
|
236
|
-
times: 2
|
|
237
|
-
)
|
|
238
|
-
# Generate the cache first
|
|
239
|
-
games = nexus_mods(api_cache_file:, api_cache_expiry: { games: 1 }).games
|
|
240
|
-
# Force a new instance of NexusMods API to run
|
|
241
|
-
reset_nexus_mods
|
|
242
|
-
sleep 2
|
|
243
|
-
# As the expiry time is 1 second, then the cache should still be invalidated
|
|
244
|
-
expect(nexus_mods(api_cache_file:, api_cache_expiry: { games: 1 }).games).to eq games
|
|
245
|
-
end
|
|
246
|
-
end
|
|
247
|
-
|
|
248
|
-
it 'uses API cache from a file, taking expiry time of the new process into account' do
|
|
249
|
-
with_api_cache_file do |api_cache_file|
|
|
250
|
-
expect_validate_user(times: 2)
|
|
251
|
-
expect_http_call_to(
|
|
252
|
-
path: '/v1/games.json',
|
|
253
|
-
json: [
|
|
254
|
-
json_game100,
|
|
255
|
-
json_game101
|
|
256
|
-
],
|
|
257
|
-
times: 2
|
|
258
|
-
)
|
|
259
|
-
# Generate the cache first
|
|
260
|
-
games = nexus_mods(api_cache_file:, api_cache_expiry: { games: 10 }).games
|
|
261
|
-
# Force a new instance of NexusMods API to run
|
|
262
|
-
reset_nexus_mods
|
|
263
|
-
sleep 2
|
|
264
|
-
# Even if the expiry time was 10 seconds while fetching the resource,
|
|
265
|
-
# if we decide it has to be 1 second now then it has to be invalidated.
|
|
266
|
-
expect(nexus_mods(api_cache_file:, api_cache_expiry: { games: 1 }).games).to eq games
|
|
267
|
-
end
|
|
268
|
-
end
|
|
269
|
-
|
|
270
321
|
it 'completes the API cache from a file' do
|
|
271
322
|
with_api_cache_file do |api_cache_file|
|
|
272
323
|
expect_validate_user(times: 3)
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: nexus_mods
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Muriel Salvan
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2023-04-
|
|
11
|
+
date: 2023-04-12 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: faraday
|