indexmap 0.4.1 → 0.4.2
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 +3 -3
- data/lib/indexmap/pinger/google.rb +6 -2
- data/lib/indexmap/pinger/index_now.rb +36 -10
- data/lib/indexmap/version.rb +1 -1
- data/lib/indexmap/writer.rb +3 -2
- data/test/indexmap/pinger/google_test.rb +27 -1
- data/test/indexmap/pinger/index_now_test.rb +65 -12
- data/test/indexmap/task_runner_test.rb +7 -5
- data/test/indexmap/writer_test.rb +19 -0
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9b0f3c8b9175d0c18c39e52b61b3934129dfa8b8b637d06ad3d0d9adc30eb995
|
|
4
|
+
data.tar.gz: 3baf06c566ce17d63e189aabfdd7f3e7b4047d5908fc6a58f3e017da5ecef1de
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 700e0cd5485cd433ceaa520a2d634eb4e5ccf93d4d8993224fae61acdf7dacd73c91029e24ff750cc58ce8704a5b00bb4ed66eff113d0693c46df75fc5aea4df
|
|
7
|
+
data.tar.gz: aa51396dad778e50b18a53606d316d5f9008ed358cecb7b75c0f7dc72f24d47a3959750102fdddafe50fbb31688256e16b07ec9c9c0ae53cb9431148593bb250
|
data/CHANGELOG.md
CHANGED
|
@@ -5,12 +5,12 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
-
## [0.4.
|
|
8
|
+
## [0.4.2] - 2026-04-23
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
###
|
|
11
|
+
### Fixed
|
|
12
12
|
|
|
13
|
-
-
|
|
13
|
+
- harden sitemap pinging and indexnow key handling (#7)
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
|
|
@@ -38,7 +38,7 @@ module Indexmap
|
|
|
38
38
|
sitemap_url = URI.join(host, File.basename(sitemap_file)).to_s
|
|
39
39
|
|
|
40
40
|
unless authorized?
|
|
41
|
-
logger.
|
|
41
|
+
logger.debug("Google Search Console does not have access to the site: #{root_domain}")
|
|
42
42
|
return {
|
|
43
43
|
status: :failed,
|
|
44
44
|
reason: :unauthorized,
|
|
@@ -62,7 +62,7 @@ module Indexmap
|
|
|
62
62
|
end
|
|
63
63
|
|
|
64
64
|
def authorized?
|
|
65
|
-
|
|
65
|
+
@authorized ||= accessible_site_urls.include?(property_identifier)
|
|
66
66
|
end
|
|
67
67
|
|
|
68
68
|
def property_identifier
|
|
@@ -104,6 +104,10 @@ module Indexmap
|
|
|
104
104
|
failures: failures
|
|
105
105
|
}
|
|
106
106
|
end
|
|
107
|
+
|
|
108
|
+
def accessible_site_urls
|
|
109
|
+
@accessible_site_urls ||= Array(webmasters_service.list_sites.site_entry).map(&:site_url)
|
|
110
|
+
end
|
|
107
111
|
end
|
|
108
112
|
end
|
|
109
113
|
end
|
|
@@ -8,6 +8,8 @@ require "time"
|
|
|
8
8
|
module Indexmap
|
|
9
9
|
module Pinger
|
|
10
10
|
class IndexNow < Base
|
|
11
|
+
KEY_FORMAT = /\A[a-f0-9]{32}\z/
|
|
12
|
+
|
|
11
13
|
def initialize(configuration: Indexmap.configuration, connection: nil)
|
|
12
14
|
super(configuration: configuration)
|
|
13
15
|
@connection = connection
|
|
@@ -41,20 +43,21 @@ module Indexmap
|
|
|
41
43
|
end
|
|
42
44
|
|
|
43
45
|
def write_key_file(key: index_now_configuration.key, path: nil)
|
|
44
|
-
key = key
|
|
46
|
+
key = normalized_configured_key(key)
|
|
45
47
|
return if key.empty?
|
|
46
48
|
|
|
47
49
|
path ||= index_now_configuration.key_path(public_path: configuration.public_path, key: key)
|
|
48
50
|
FileUtils.mkdir_p(path.dirname)
|
|
49
|
-
File.write(path,
|
|
51
|
+
File.write(path, key)
|
|
50
52
|
path
|
|
51
53
|
end
|
|
52
54
|
|
|
53
55
|
def ensure_key_file
|
|
54
|
-
configured_key = index_now_configuration.key
|
|
56
|
+
configured_key = normalized_configured_key(index_now_configuration.key)
|
|
55
57
|
return write_key_file(key: configured_key) unless configured_key.empty?
|
|
56
58
|
|
|
57
|
-
|
|
59
|
+
existing_path = existing_key_file
|
|
60
|
+
return existing_path if existing_path
|
|
58
61
|
|
|
59
62
|
key = generated_key
|
|
60
63
|
write_key_file(key: key, path: configuration.public_path.join("#{key}.txt"))
|
|
@@ -143,6 +146,9 @@ module Indexmap
|
|
|
143
146
|
|
|
144
147
|
def submit_batch(api_key:, urls:)
|
|
145
148
|
payload = {host: hostname, key: api_key, urlList: urls}
|
|
149
|
+
location = key_location(api_key: api_key)
|
|
150
|
+
payload[:keyLocation] = location if location
|
|
151
|
+
|
|
146
152
|
response = index_now_connection.post("/indexnow") do |request|
|
|
147
153
|
request.headers["Content-Type"] = "application/json"
|
|
148
154
|
request.body = payload.to_json
|
|
@@ -168,30 +174,50 @@ module Indexmap
|
|
|
168
174
|
end
|
|
169
175
|
|
|
170
176
|
def read_api_key
|
|
171
|
-
configured_key = index_now_configuration.key
|
|
177
|
+
configured_key = normalized_configured_key(index_now_configuration.key)
|
|
172
178
|
return configured_key unless configured_key.empty?
|
|
173
179
|
|
|
174
|
-
existing_key_file&.read
|
|
180
|
+
existing_key_file&.read
|
|
175
181
|
end
|
|
176
182
|
|
|
177
183
|
def existing_key_file
|
|
178
184
|
configured_path = index_now_configuration.key_path(public_path: configuration.public_path)
|
|
179
185
|
return configured_path if valid_key_file?(configured_path)
|
|
180
186
|
|
|
181
|
-
configuration.public_path.glob("*.txt").find { |file| valid_key_file?(file) }
|
|
187
|
+
configuration.public_path.glob("*.txt").sort.find { |file| valid_key_file?(file) }
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
def key_location(api_key:)
|
|
191
|
+
path = index_now_configuration.key_path(public_path: configuration.public_path, key: api_key) || existing_key_file
|
|
192
|
+
return unless path
|
|
193
|
+
|
|
194
|
+
public_path = configuration.public_path.expand_path
|
|
195
|
+
key_path = path.expand_path
|
|
196
|
+
relative_path = key_path.relative_path_from(public_path)
|
|
197
|
+
|
|
198
|
+
URI.join("#{host}/", relative_path.to_s).to_s
|
|
199
|
+
rescue ArgumentError
|
|
200
|
+
nil
|
|
182
201
|
end
|
|
183
202
|
|
|
184
203
|
def valid_key_file?(path)
|
|
185
204
|
return false unless path&.file?
|
|
186
205
|
|
|
187
206
|
filename = path.basename(".txt").to_s
|
|
188
|
-
return false unless filename.match?(
|
|
207
|
+
return false unless filename.match?(KEY_FORMAT)
|
|
189
208
|
|
|
190
|
-
path.read
|
|
209
|
+
path.read == filename
|
|
191
210
|
end
|
|
192
211
|
|
|
193
212
|
def generated_key
|
|
194
|
-
SecureRandom.
|
|
213
|
+
SecureRandom.hex(16)
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
def normalized_configured_key(value)
|
|
217
|
+
key = value.to_s.strip
|
|
218
|
+
return key if key.empty? || key.match?(KEY_FORMAT)
|
|
219
|
+
|
|
220
|
+
raise ConfigurationError, "IndexNow key must be a 32-character lowercase hexadecimal string"
|
|
195
221
|
end
|
|
196
222
|
|
|
197
223
|
def summarize_results(results)
|
data/lib/indexmap/version.rb
CHANGED
data/lib/indexmap/writer.rb
CHANGED
|
@@ -82,7 +82,8 @@ module Indexmap
|
|
|
82
82
|
sitemap_sections.each do |section|
|
|
83
83
|
lines << " <sitemap>"
|
|
84
84
|
lines << " <loc>#{escape(index_loc(section.filename))}</loc>"
|
|
85
|
-
|
|
85
|
+
lastmod = section_lastmod(section)
|
|
86
|
+
lines << " <lastmod>#{format_lastmod(lastmod)}</lastmod>" if lastmod
|
|
86
87
|
lines << " </sitemap>"
|
|
87
88
|
end
|
|
88
89
|
|
|
@@ -102,7 +103,7 @@ module Indexmap
|
|
|
102
103
|
|
|
103
104
|
def section_lastmod(section)
|
|
104
105
|
timestamps = Array(section.entries).map { |entry| comparable_lastmod(normalize_entry(entry).lastmod) }.compact
|
|
105
|
-
timestamps.max
|
|
106
|
+
timestamps.max
|
|
106
107
|
end
|
|
107
108
|
|
|
108
109
|
def format_lastmod(value)
|
|
@@ -8,13 +8,15 @@ class IndexmapPingerGoogleTest < Minitest::Test
|
|
|
8
8
|
|
|
9
9
|
class FakeWebmastersService
|
|
10
10
|
attr_accessor :authorization
|
|
11
|
-
attr_reader :submitted
|
|
11
|
+
attr_reader :submitted, :list_sites_calls
|
|
12
12
|
|
|
13
13
|
def initialize(site_urls:)
|
|
14
14
|
@site_urls = site_urls
|
|
15
|
+
@list_sites_calls = 0
|
|
15
16
|
end
|
|
16
17
|
|
|
17
18
|
def list_sites
|
|
19
|
+
@list_sites_calls += 1
|
|
18
20
|
SiteList.new(@site_urls.map { |site_url| SiteEntry.new(site_url) })
|
|
19
21
|
end
|
|
20
22
|
|
|
@@ -51,6 +53,7 @@ class IndexmapPingerGoogleTest < Minitest::Test
|
|
|
51
53
|
assert_equal ["sc-domain:example.com", "https://www.example.com/sitemap.xml"], service.submitted
|
|
52
54
|
assert_equal :submitted, result[:status]
|
|
53
55
|
assert_equal 1, result[:sitemap_count]
|
|
56
|
+
assert_equal 1, service.list_sites_calls
|
|
54
57
|
end
|
|
55
58
|
end
|
|
56
59
|
|
|
@@ -114,4 +117,27 @@ class IndexmapPingerGoogleTest < Minitest::Test
|
|
|
114
117
|
assert_nil service.submitted
|
|
115
118
|
end
|
|
116
119
|
end
|
|
120
|
+
|
|
121
|
+
def test_google_authorization_requires_exact_property_match
|
|
122
|
+
Dir.mktmpdir do |dir|
|
|
123
|
+
public_path = Pathname(dir)
|
|
124
|
+
public_path.join("sitemap.xml").write("<sitemapindex/>")
|
|
125
|
+
|
|
126
|
+
configuration = Indexmap::Configuration.new
|
|
127
|
+
configuration.base_url = "https://www.example.com"
|
|
128
|
+
configuration.public_path = public_path
|
|
129
|
+
configuration.google.credentials = "{\"type\":\"service_account\"}"
|
|
130
|
+
|
|
131
|
+
service = FakeWebmastersService.new(site_urls: ["sc-domain:myexample.com"])
|
|
132
|
+
result = Indexmap::Pinger::Google.new(
|
|
133
|
+
configuration: configuration,
|
|
134
|
+
service: service,
|
|
135
|
+
credentials_builder: ->(**) { :fake_authorizer }
|
|
136
|
+
).ping
|
|
137
|
+
|
|
138
|
+
assert_equal :failed, result[:status]
|
|
139
|
+
assert_equal :unauthorized, result[:failures].first[:reason]
|
|
140
|
+
assert_nil service.submitted
|
|
141
|
+
end
|
|
142
|
+
end
|
|
117
143
|
end
|
|
@@ -3,17 +3,19 @@
|
|
|
3
3
|
require "test_helper"
|
|
4
4
|
|
|
5
5
|
class IndexmapPingerIndexNowTest < Minitest::Test
|
|
6
|
+
VALID_KEY = "1234567890abcdef1234567890abcdef"
|
|
7
|
+
|
|
6
8
|
def test_writes_key_file_from_configuration
|
|
7
9
|
Dir.mktmpdir do |dir|
|
|
8
10
|
configuration = Indexmap::Configuration.new
|
|
9
11
|
configuration.base_url = "https://www.example.com"
|
|
10
12
|
configuration.public_path = Pathname(dir)
|
|
11
|
-
configuration.index_now.key =
|
|
13
|
+
configuration.index_now.key = VALID_KEY
|
|
12
14
|
|
|
13
15
|
path = Indexmap::Pinger::IndexNow.new(configuration: configuration).write_key_file
|
|
14
16
|
|
|
15
|
-
assert_equal Pathname(dir).join("
|
|
16
|
-
assert_equal
|
|
17
|
+
assert_equal Pathname(dir).join("#{VALID_KEY}.txt"), path
|
|
18
|
+
assert_equal VALID_KEY, path.read
|
|
17
19
|
end
|
|
18
20
|
end
|
|
19
21
|
|
|
@@ -25,16 +27,16 @@ class IndexmapPingerIndexNowTest < Minitest::Test
|
|
|
25
27
|
|
|
26
28
|
path = Indexmap::Pinger::IndexNow.new(configuration: configuration).ensure_key_file
|
|
27
29
|
|
|
28
|
-
assert_match(/\A[a-
|
|
29
|
-
assert_equal
|
|
30
|
+
assert_match(/\A[a-f0-9]{32}\.txt\z/, path.basename.to_s)
|
|
31
|
+
assert_equal path.basename(".txt").to_s, path.read
|
|
30
32
|
end
|
|
31
33
|
end
|
|
32
34
|
|
|
33
35
|
def test_pings_using_existing_key_file_when_key_is_not_configured
|
|
34
36
|
Dir.mktmpdir do |dir|
|
|
35
37
|
public_path = Pathname(dir)
|
|
36
|
-
key_path = public_path.join("
|
|
37
|
-
key_path.write(
|
|
38
|
+
key_path = public_path.join("#{VALID_KEY}.txt")
|
|
39
|
+
key_path.write(VALID_KEY)
|
|
38
40
|
write_sitemap_files(
|
|
39
41
|
public_path,
|
|
40
42
|
marketing_lastmod: "2026-04-18T00:00:00Z",
|
|
@@ -52,7 +54,8 @@ class IndexmapPingerIndexNowTest < Minitest::Test
|
|
|
52
54
|
|
|
53
55
|
assert_requested(:post, indexnow_url, times: 1) do |request|
|
|
54
56
|
payload = JSON.parse(request.body)
|
|
55
|
-
assert_equal
|
|
57
|
+
assert_equal VALID_KEY, payload.fetch("key")
|
|
58
|
+
assert_equal "https://www.example.com/#{VALID_KEY}.txt", payload.fetch("keyLocation")
|
|
56
59
|
end
|
|
57
60
|
assert_equal :submitted, result[:status]
|
|
58
61
|
assert_equal 2, result[:url_count]
|
|
@@ -60,6 +63,24 @@ class IndexmapPingerIndexNowTest < Minitest::Test
|
|
|
60
63
|
end
|
|
61
64
|
end
|
|
62
65
|
|
|
66
|
+
def test_ignores_existing_key_file_with_trailing_newline
|
|
67
|
+
Dir.mktmpdir do |dir|
|
|
68
|
+
public_path = Pathname(dir)
|
|
69
|
+
invalid_key_path = public_path.join("1234567890abcdef1234567890abcdef.txt")
|
|
70
|
+
invalid_key_path.write("#{VALID_KEY}\n")
|
|
71
|
+
|
|
72
|
+
configuration = Indexmap::Configuration.new
|
|
73
|
+
configuration.base_url = "https://www.example.com"
|
|
74
|
+
configuration.public_path = public_path
|
|
75
|
+
|
|
76
|
+
path = Indexmap::Pinger::IndexNow.new(configuration: configuration).ensure_key_file
|
|
77
|
+
|
|
78
|
+
refute_equal invalid_key_path, path
|
|
79
|
+
assert_match(/\A[a-f0-9]{32}\.txt\z/, path.basename.to_s)
|
|
80
|
+
assert_equal path.basename(".txt").to_s, path.read
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
63
84
|
def test_pings_all_sitemap_urls_when_no_cutoff_is_provided
|
|
64
85
|
Dir.mktmpdir do |dir|
|
|
65
86
|
public_path = Pathname(dir)
|
|
@@ -72,7 +93,7 @@ class IndexmapPingerIndexNowTest < Minitest::Test
|
|
|
72
93
|
configuration = Indexmap::Configuration.new
|
|
73
94
|
configuration.base_url = "https://www.example.com"
|
|
74
95
|
configuration.public_path = public_path
|
|
75
|
-
configuration.index_now.key =
|
|
96
|
+
configuration.index_now.key = VALID_KEY
|
|
76
97
|
|
|
77
98
|
indexnow_url = "https://api.indexnow.org/indexnow"
|
|
78
99
|
stub_request(:post, indexnow_url).to_return(status: 200, body: "", headers: {})
|
|
@@ -85,6 +106,7 @@ class IndexmapPingerIndexNowTest < Minitest::Test
|
|
|
85
106
|
"https://www.example.com/pages/features",
|
|
86
107
|
"https://www.example.com/insights/us/restaurants/overview"
|
|
87
108
|
].sort, payload.fetch("urlList").sort
|
|
109
|
+
assert_equal "https://www.example.com/#{VALID_KEY}.txt", payload.fetch("keyLocation")
|
|
88
110
|
end
|
|
89
111
|
assert_equal :submitted, result[:status]
|
|
90
112
|
assert_equal 2, result[:url_count]
|
|
@@ -104,7 +126,7 @@ class IndexmapPingerIndexNowTest < Minitest::Test
|
|
|
104
126
|
configuration = Indexmap::Configuration.new
|
|
105
127
|
configuration.base_url = "https://www.example.com"
|
|
106
128
|
configuration.public_path = public_path
|
|
107
|
-
configuration.index_now.key =
|
|
129
|
+
configuration.index_now.key = VALID_KEY
|
|
108
130
|
|
|
109
131
|
indexnow_url = "https://api.indexnow.org/indexnow"
|
|
110
132
|
stub_request(:post, indexnow_url).to_return(status: 200, body: "", headers: {})
|
|
@@ -155,7 +177,7 @@ class IndexmapPingerIndexNowTest < Minitest::Test
|
|
|
155
177
|
configuration = Indexmap::Configuration.new
|
|
156
178
|
configuration.base_url = "https://www.example.com"
|
|
157
179
|
configuration.public_path = public_path
|
|
158
|
-
configuration.index_now.key =
|
|
180
|
+
configuration.index_now.key = VALID_KEY
|
|
159
181
|
|
|
160
182
|
with_env("INDEXNOW_DRY_RUN" => "1") do
|
|
161
183
|
result = Indexmap::Pinger::IndexNow.new(configuration: configuration).ping
|
|
@@ -179,7 +201,7 @@ class IndexmapPingerIndexNowTest < Minitest::Test
|
|
|
179
201
|
configuration = Indexmap::Configuration.new
|
|
180
202
|
configuration.base_url = "https://www.example.com"
|
|
181
203
|
configuration.public_path = public_path
|
|
182
|
-
configuration.index_now.key =
|
|
204
|
+
configuration.index_now.key = VALID_KEY
|
|
183
205
|
|
|
184
206
|
indexnow_url = "https://api.indexnow.org/indexnow"
|
|
185
207
|
stub_request(:post, indexnow_url).to_return(status: 500, body: "boom", headers: {})
|
|
@@ -192,6 +214,37 @@ class IndexmapPingerIndexNowTest < Minitest::Test
|
|
|
192
214
|
end
|
|
193
215
|
end
|
|
194
216
|
|
|
217
|
+
def test_rejects_invalid_configured_key
|
|
218
|
+
Dir.mktmpdir do |dir|
|
|
219
|
+
configuration = Indexmap::Configuration.new
|
|
220
|
+
configuration.base_url = "https://www.example.com"
|
|
221
|
+
configuration.public_path = Pathname(dir)
|
|
222
|
+
configuration.index_now.key = "test-key"
|
|
223
|
+
|
|
224
|
+
error = assert_raises(Indexmap::ConfigurationError) do
|
|
225
|
+
Indexmap::Pinger::IndexNow.new(configuration: configuration).ping
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
assert_equal "IndexNow key must be a 32-character lowercase hexadecimal string", error.message
|
|
229
|
+
end
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
def test_reuses_existing_key_file_deterministically
|
|
233
|
+
Dir.mktmpdir do |dir|
|
|
234
|
+
public_path = Pathname(dir)
|
|
235
|
+
public_path.join("ffffffffffffffffffffffffffffffff.txt").write("ffffffffffffffffffffffffffffffff")
|
|
236
|
+
public_path.join("00000000000000000000000000000000.txt").write("00000000000000000000000000000000")
|
|
237
|
+
|
|
238
|
+
configuration = Indexmap::Configuration.new
|
|
239
|
+
configuration.base_url = "https://www.example.com"
|
|
240
|
+
configuration.public_path = public_path
|
|
241
|
+
|
|
242
|
+
path = Indexmap::Pinger::IndexNow.new(configuration: configuration).ensure_key_file
|
|
243
|
+
|
|
244
|
+
assert_equal public_path.join("00000000000000000000000000000000.txt"), path
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
|
|
195
248
|
private
|
|
196
249
|
|
|
197
250
|
def with_env(overrides)
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
require "test_helper"
|
|
4
4
|
|
|
5
5
|
class IndexmapTaskRunnerTest < Minitest::Test
|
|
6
|
+
VALID_KEY = "1234567890abcdef1234567890abcdef"
|
|
7
|
+
|
|
6
8
|
def test_create_removes_existing_sitemap_files_writes_new_sitemap_and_key_file
|
|
7
9
|
Dir.mktmpdir do |dir|
|
|
8
10
|
public_path = Pathname(dir)
|
|
@@ -18,15 +20,15 @@ class IndexmapTaskRunnerTest < Minitest::Test
|
|
|
18
20
|
entries: [Indexmap::Entry.new(loc: "https://example.com/about")]
|
|
19
21
|
)
|
|
20
22
|
]
|
|
21
|
-
configuration.index_now.key =
|
|
23
|
+
configuration.index_now.key = VALID_KEY
|
|
22
24
|
|
|
23
25
|
result = Indexmap::TaskRunner.new(configuration: configuration).create
|
|
24
26
|
|
|
25
27
|
assert_equal false, public_path.join("sitemap-pages.xml.gz").exist?
|
|
26
28
|
assert_includes public_path.join("sitemap.xml").read, "<sitemapindex"
|
|
27
|
-
assert_equal
|
|
29
|
+
assert_equal VALID_KEY, public_path.join("#{VALID_KEY}.txt").read
|
|
28
30
|
assert_equal [public_path.join("sitemap-pages.xml").to_s, public_path.join("sitemap.xml").to_s], result[:files]
|
|
29
|
-
assert_equal public_path.join("
|
|
31
|
+
assert_equal public_path.join("#{VALID_KEY}.txt"), result[:index_now_key_path]
|
|
30
32
|
end
|
|
31
33
|
end
|
|
32
34
|
|
|
@@ -56,8 +58,8 @@ class IndexmapTaskRunnerTest < Minitest::Test
|
|
|
56
58
|
|
|
57
59
|
result = Indexmap::TaskRunner.new(configuration: configuration).write_index_now_key(generate_if_missing: true)
|
|
58
60
|
|
|
59
|
-
assert_match(/\A[a-
|
|
60
|
-
assert_equal
|
|
61
|
+
assert_match(/\A[a-f0-9]{32}\.txt\z/, result.basename.to_s)
|
|
62
|
+
assert_equal result.basename(".txt").to_s, result.read
|
|
61
63
|
end
|
|
62
64
|
end
|
|
63
65
|
end
|
|
@@ -77,4 +77,23 @@ class IndexmapWriterTest < Minitest::Test
|
|
|
77
77
|
refute File.exist?(File.join(directory, "sitemap-pages.xml"))
|
|
78
78
|
end
|
|
79
79
|
end
|
|
80
|
+
|
|
81
|
+
def test_omits_sitemap_index_lastmod_when_sections_have_no_lastmod
|
|
82
|
+
Dir.mktmpdir do |directory|
|
|
83
|
+
Indexmap::Writer.new(
|
|
84
|
+
sections: [
|
|
85
|
+
Indexmap::Section.new(
|
|
86
|
+
filename: "sitemap-pages.xml",
|
|
87
|
+
entries: [Indexmap::Entry.new(loc: "https://example.com/about")]
|
|
88
|
+
)
|
|
89
|
+
],
|
|
90
|
+
public_path: directory,
|
|
91
|
+
base_url: "https://example.com"
|
|
92
|
+
).write
|
|
93
|
+
|
|
94
|
+
index_xml = File.read(File.join(directory, "sitemap.xml"))
|
|
95
|
+
|
|
96
|
+
refute_includes index_xml, "<lastmod>"
|
|
97
|
+
end
|
|
98
|
+
end
|
|
80
99
|
end
|