haveapi 0.32.1 → 0.32.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/.gitignore +3 -8
- data/README.md +3 -422
- data/Rakefile +17 -7
- data/benchmarks/performance_compare.rb +27 -6
- data/doc/cs/client-examples.md +535 -0
- data/doc/cs/create-client.md +118 -0
- data/doc/cs/json-schema.html +1182 -0
- data/doc/cs/protocol.md +595 -0
- data/doc/cs/readme.md +432 -0
- data/doc/cs/typed-input-validation.md +122 -0
- data/doc/{client-examples.md → en/client-examples.md} +20 -10
- data/doc/{documentation-ui.md → en/documentation-ui.md} +42 -6
- data/doc/{performance.md → en/performance.md} +11 -0
- data/doc/{protocol.md → en/protocol.md} +2 -2
- data/doc/en/readme.md +423 -0
- data/haveapi.gemspec +2 -2
- data/lib/haveapi/client_example.rb +18 -5
- data/lib/haveapi/client_examples/curl.rb +5 -5
- data/lib/haveapi/client_examples/dynamic_helpers.rb +10 -10
- data/lib/haveapi/client_examples/go_client.rb +1 -1
- data/lib/haveapi/client_examples/http.rb +4 -4
- data/lib/haveapi/client_examples/js_client.rb +10 -10
- data/lib/haveapi/client_examples/php_client.rb +24 -25
- data/lib/haveapi/client_examples/python_client.rb +11 -11
- data/lib/haveapi/client_examples/ruby_cli.rb +6 -9
- data/lib/haveapi/client_examples/ruby_client.rb +24 -16
- data/lib/haveapi/client_examples/rust_client.rb +1 -1
- data/lib/haveapi/client_examples/ts_generated_client.rb +1 -1
- data/lib/haveapi/documentation_context.rb +14 -2
- data/lib/haveapi/documentation_helpers.rb +92 -15
- data/lib/haveapi/documentation_locale.rb +65 -0
- data/lib/haveapi/documentation_oauth.rb +12 -12
- data/lib/haveapi/documentation_search.rb +5 -5
- data/lib/haveapi/documentation_validators.rb +43 -33
- data/lib/haveapi/locales/cs.yml +468 -0
- data/lib/haveapi/locales/en.yml +467 -0
- data/lib/haveapi/public/css/documentation.css +8 -4
- data/lib/haveapi/public/js/documentation.js +73 -20
- data/lib/haveapi/server.rb +32 -47
- data/lib/haveapi/shared_documentation_helpers.rb +53 -5
- data/lib/haveapi/version.rb +1 -1
- data/lib/haveapi/views/doc_layout.erb +3 -2
- data/lib/haveapi/views/doc_sidebars/create-client.erb +10 -10
- data/lib/haveapi/views/doc_sidebars/json-schema.erb +2 -2
- data/lib/haveapi/views/doc_sidebars/protocol.erb +24 -24
- data/lib/haveapi/views/documentation/search_form.erb +5 -4
- data/lib/haveapi/views/documentation/search_results.erb +6 -6
- data/lib/haveapi/views/index.erb +3 -3
- data/lib/haveapi/views/main_layout.erb +4 -4
- data/lib/haveapi/views/shared_documentation.erb +8 -5
- data/lib/haveapi/views/shared_sidebar.erb +11 -11
- data/lib/haveapi/views/version_page/auth_body.erb +7 -7
- data/lib/haveapi/views/version_page/client_auth.erb +1 -1
- data/lib/haveapi/views/version_page/client_example.erb +1 -1
- data/lib/haveapi/views/version_page/client_init.erb +1 -1
- data/lib/haveapi/views/version_page/client_overview.erb +7 -5
- data/lib/haveapi/views/version_page/example_panels.erb +5 -2
- data/lib/haveapi/views/version_page/resource_body.erb +24 -24
- data/lib/haveapi/views/version_page/resource_directory.erb +2 -2
- data/lib/haveapi/views/version_page/usage.erb +5 -5
- data/lib/haveapi/views/version_page.erb +11 -11
- data/lib/haveapi/views/version_sidebar/auth_nav.erb +2 -2
- data/lib/haveapi/views/version_sidebar/authentication_control.erb +8 -8
- data/lib/haveapi/views/version_sidebar/authentication_status.erb +1 -1
- data/lib/haveapi/views/version_sidebar/brand.erb +16 -5
- data/lib/haveapi/views/version_sidebar.erb +33 -18
- data/spec/client_examples/assets/documentation_test.cjs +107 -9
- data/spec/client_examples/comment_capture.rb +72 -0
- data/spec/client_examples/comments_spec.rb +162 -0
- data/spec/client_examples/context_spec.rb +18 -2
- data/spec/client_examples/detail_spec.rb +68 -0
- data/spec/documentation/client_overview_spec.rb +60 -0
- data/spec/documentation/example_selection_spec.rb +192 -0
- data/spec/documentation/language_settings_spec.rb +132 -0
- data/spec/documentation/locale_spec.rb +367 -0
- data/spec/documentation/navigation_spec.rb +61 -3
- data/spec/documentation/oauth_spec.rb +42 -0
- data/spec/documentation/search_index_routes_spec.rb +8 -4
- data/spec/documentation/search_spec.rb +1 -1
- data/spec/documentation/shared_pages_spec.rb +63 -2
- data/spec/documentation/validators_spec.rb +25 -0
- data/spec/extensions/exception_mailer_spec.rb +2 -2
- data/spec/packaging_spec.rb +68 -9
- data/spec/performance/event_baseline_spec.rb +1 -1
- data/spec/performance/source_versions_spec.rb +111 -2
- metadata +24 -11
- /data/doc/{create-client.md → en/create-client.md} +0 -0
- /data/doc/{documentation-oauth.md → en/documentation-oauth.md} +0 -0
- /data/doc/{json-schema.html → en/json-schema.html} +0 -0
- /data/doc/{typed-input-validation.md → en/typed-input-validation.md} +0 -0
|
@@ -120,4 +120,29 @@ describe HaveAPI::DocumentationValidators do
|
|
|
120
120
|
expect(render(payload, { 'extra' => payload })).to include('<th scope="row"><script>&"</th>')
|
|
121
121
|
expect(Marshal.dump(options)).to eq(before)
|
|
122
122
|
end
|
|
123
|
+
|
|
124
|
+
it 'localizes framework presentation while preserving metadata and machine values' do
|
|
125
|
+
validators = {
|
|
126
|
+
present: { empty: false }, include: { values: { 'ready' => 'Application label' } },
|
|
127
|
+
number: { min: 2, step: 3, even: true }, length: { min: 2, max: 8 },
|
|
128
|
+
custom: 'Application rule', extension: { 'supplied' => 'Untranslated metadata' }
|
|
129
|
+
}
|
|
130
|
+
before = Marshal.dump(validators)
|
|
131
|
+
html = I18n.with_locale(:cs) { described_class.render(validators, type: 'String') }
|
|
132
|
+
|
|
133
|
+
expect(html).to include('<caption>Validační pravidla</caption>', '<th scope="col">Pravidlo</th>',
|
|
134
|
+
'<th scope="col">Podrobnosti</th>', 'Musí být uvedeno', 'Povolené hodnoty',
|
|
135
|
+
'<code>ready</code>: Application label', 'Application rule', 'Untranslated metadata')
|
|
136
|
+
expect(html).not_to include('Validation rules', 'Allowed values', 'Minimum length:')
|
|
137
|
+
expect(Marshal.dump(validators)).to eq(before)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
it 'escapes translated text and interpolated metadata independently' do
|
|
141
|
+
html = I18n.with_locale(:cs) do
|
|
142
|
+
render(:confirm, { parameter: '<script>&', equal: false })
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
expect(html).to include('Musí se lišit od parametru <code><script>&</code>.')
|
|
146
|
+
expect(html).not_to include('<script>', '&lt;')
|
|
147
|
+
end
|
|
123
148
|
end
|
|
@@ -125,7 +125,7 @@ describe HaveAPI::Extensions::ExceptionMailer do
|
|
|
125
125
|
it 'does not mail a missing JSON schema documentation file' do
|
|
126
126
|
mailer = new_mailer
|
|
127
127
|
calls = collect_mail_calls(mailer)
|
|
128
|
-
doc_path = File.
|
|
128
|
+
doc_path = File.expand_path('../../doc/en/json-schema.html', app.settings.root)
|
|
129
129
|
allow(File).to receive(:read).and_call_original
|
|
130
130
|
allow(File).to receive(:read).with(doc_path).and_raise(Errno::ENOENT, doc_path)
|
|
131
131
|
|
|
@@ -142,7 +142,7 @@ describe HaveAPI::Extensions::ExceptionMailer do
|
|
|
142
142
|
calls = collect_mail_calls(mailer)
|
|
143
143
|
app.set :raise_errors, false
|
|
144
144
|
app.set :show_exceptions, false
|
|
145
|
-
doc_path = File.
|
|
145
|
+
doc_path = File.expand_path('../../doc/en/json-schema.html', app.settings.root)
|
|
146
146
|
allow(File).to receive(:read).and_call_original
|
|
147
147
|
allow(File).to receive(:read).with(doc_path).and_raise(Errno::EACCES, doc_path)
|
|
148
148
|
|
data/spec/packaging_spec.rb
CHANGED
|
@@ -9,7 +9,12 @@ require 'tmpdir'
|
|
|
9
9
|
|
|
10
10
|
describe HaveAPI::Server do
|
|
11
11
|
def required_docs
|
|
12
|
-
%w[
|
|
12
|
+
%w[protocol.png en/documentation-ui.md en/documentation-oauth.md en/performance.md] +
|
|
13
|
+
%w[en cs].flat_map do |locale|
|
|
14
|
+
%w[readme.md protocol.md create-client.md typed-input-validation.md client-examples.md json-schema.html].map do |name|
|
|
15
|
+
"#{locale}/#{name}"
|
|
16
|
+
end
|
|
17
|
+
end
|
|
13
18
|
end
|
|
14
19
|
|
|
15
20
|
before(:context) do
|
|
@@ -22,14 +27,15 @@ describe HaveAPI::Server do
|
|
|
22
27
|
Rake::Task[:build].invoke
|
|
23
28
|
end
|
|
24
29
|
|
|
25
|
-
%i[missing empty].each do |condition|
|
|
26
|
-
it "rejects a direct build with #{condition}
|
|
30
|
+
%w[en/json-schema.html cs/json-schema.html cs/protocol.md].product(%i[missing empty]).each do |document, condition|
|
|
31
|
+
it "rejects a direct build with #{condition} #{document}" do
|
|
27
32
|
Dir.mktmpdir('haveapi-doc-check') do |dir|
|
|
28
33
|
FileUtils.mkdir_p(File.join(dir, 'doc'))
|
|
29
34
|
required_docs.each do |name|
|
|
30
|
-
next if name ==
|
|
35
|
+
next if name == document && condition == :missing
|
|
31
36
|
|
|
32
|
-
content = name ==
|
|
37
|
+
content = name == document && condition == :empty ? '' : 'document'
|
|
38
|
+
FileUtils.mkdir_p(File.dirname(File.join(dir, 'doc', name)))
|
|
33
39
|
File.write(File.join(dir, 'doc', name), content)
|
|
34
40
|
end
|
|
35
41
|
|
|
@@ -38,12 +44,42 @@ describe HaveAPI::Server do
|
|
|
38
44
|
expect { invoke_build }.to raise_error(SystemExit) do |error|
|
|
39
45
|
expect(error.status).to eq(1)
|
|
40
46
|
end
|
|
41
|
-
end.to output(
|
|
47
|
+
end.to output(/#{Regexp.escape(document)}.*Run `make doc`/).to_stderr
|
|
42
48
|
end
|
|
43
49
|
end
|
|
44
50
|
end
|
|
45
51
|
end
|
|
46
52
|
|
|
53
|
+
it 'copies localized schema documentation without application gems or Bundler' do
|
|
54
|
+
root = File.expand_path('../../..', __dir__)
|
|
55
|
+
Dir.mktmpdir('haveapi-copydoc') do |dir|
|
|
56
|
+
destination = File.join(dir, 'server')
|
|
57
|
+
empty_gems = File.join(dir, 'empty-gems')
|
|
58
|
+
FileUtils.mkdir_p(empty_gems)
|
|
59
|
+
environment = {
|
|
60
|
+
'GEM_HOME' => empty_gems,
|
|
61
|
+
'GEM_PATH' => empty_gems,
|
|
62
|
+
'RUBYLIB' => nil,
|
|
63
|
+
'RUBYOPT' => nil,
|
|
64
|
+
'RUBYGEMS_GEMDEPS' => nil
|
|
65
|
+
}
|
|
66
|
+
stdout, stderr, status = Bundler.with_unbundled_env do
|
|
67
|
+
Open3.capture3(environment, File.join(root, 'utils/copydoc.sh'), destination, chdir: root)
|
|
68
|
+
end
|
|
69
|
+
expect(status.success?).to be(true), "Isolated documentation copy failed: #{stdout}#{stderr}"
|
|
70
|
+
|
|
71
|
+
schemas = %w[en cs].map do |locale|
|
|
72
|
+
body = File.read(File.join(destination, 'doc', locale, 'json-schema.html'))
|
|
73
|
+
heading = ::I18n.t('haveapi.documentation.schema.envelope', locale:, raise: true)
|
|
74
|
+
expect(body).to include(%(<h1 id="envelope">#{ERB::Util.html_escape(heading)}</h1>))
|
|
75
|
+
code = body.scan(%r{<pre><code>(.*?)</code></pre>}m).flatten
|
|
76
|
+
expect(code.length).to eq(4)
|
|
77
|
+
code
|
|
78
|
+
end
|
|
79
|
+
expect(schemas[0]).to eq(schemas[1])
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
47
83
|
it 'ships and serves shared documentation from the built gem' do
|
|
48
84
|
invoke_build
|
|
49
85
|
gem_path = File.expand_path("../pkg/haveapi-#{HaveAPI::VERSION}.gem", __dir__)
|
|
@@ -85,13 +121,18 @@ describe HaveAPI::Server do
|
|
|
85
121
|
server.use_version(1)
|
|
86
122
|
server.mount('/')
|
|
87
123
|
request = Rack::MockRequest.new(server.app)
|
|
88
|
-
responses = %w[/ /doc /doc/index /doc/index.md /doc/readme /doc/json-schema /doc/protocol.md /doc/create-client.md /doc/client-examples.md /js/highlight-LICENSE].to_h do |path|
|
|
89
|
-
response = request.get(path, 'HTTP_HOST' => 'localhost')
|
|
124
|
+
responses = %w[/ /doc /doc/index /doc/index.md /doc/readme /doc/json-schema /doc/protocol.md /doc/create-client.md /doc/client-examples.md /doc/typed-input-validation /js/highlight-LICENSE].to_h do |path|
|
|
125
|
+
response = request.get(path, 'HTTP_HOST' => 'localhost', 'HTTP_ACCEPT_LANGUAGE' => 'en')
|
|
90
126
|
[path, { status: response.status, type: response.content_type, cache_control: response['Cache-Control'], body: response.body }]
|
|
91
127
|
end
|
|
128
|
+
translated = %w[/doc /doc/index /doc/index.md /doc/readme /doc/protocol.md /doc/create-client.md /doc/typed-input-validation /doc/client-examples.md /doc/json-schema /doc/documentation-ui].to_h do |path|
|
|
129
|
+
response = request.get(path, 'HTTP_HOST' => 'localhost', 'HTTP_ACCEPT_LANGUAGE' => 'cs-CZ')
|
|
130
|
+
[path, { status: response.status, body: response.body }]
|
|
131
|
+
end
|
|
92
132
|
puts JSON.generate({
|
|
93
133
|
framework: HaveAPI::Server.instance_method(:mount).source_location.first,
|
|
94
|
-
responses: responses
|
|
134
|
+
responses: responses,
|
|
135
|
+
translated: translated
|
|
95
136
|
})
|
|
96
137
|
RUBY
|
|
97
138
|
|
|
@@ -128,6 +169,7 @@ describe HaveAPI::Server do
|
|
|
128
169
|
'/doc/protocol.md' => 'Protocol definition',
|
|
129
170
|
'/doc/create-client.md' => 'Client definition',
|
|
130
171
|
'/doc/client-examples.md' => 'Client examples',
|
|
172
|
+
'/doc/typed-input-validation' => 'Typed input validation',
|
|
131
173
|
'/js/highlight-LICENSE' => 'Copyright'
|
|
132
174
|
}.each do |path, heading|
|
|
133
175
|
response = result.fetch('responses').fetch(path)
|
|
@@ -140,6 +182,23 @@ describe HaveAPI::Server do
|
|
|
140
182
|
expect(response.fetch('body')).to include('data-docs', '/js/documentation.js', '/css/documentation.css')
|
|
141
183
|
expect(response.fetch('body')).not_to include('/js/main.js', '/css/bootstrap')
|
|
142
184
|
end
|
|
185
|
+
{
|
|
186
|
+
'/doc' => 'Serverová implementace',
|
|
187
|
+
'/doc/index' => 'Serverová implementace',
|
|
188
|
+
'/doc/index.md' => 'Serverová implementace',
|
|
189
|
+
'/doc/readme' => 'Serverová implementace',
|
|
190
|
+
'/doc/protocol.md' => 'Definice protokolu',
|
|
191
|
+
'/doc/create-client.md' => 'Definice klienta',
|
|
192
|
+
'/doc/typed-input-validation' => 'Validace typovaných vstupů',
|
|
193
|
+
'/doc/client-examples.md' => 'Klientské příklady',
|
|
194
|
+
'/doc/json-schema' => 'Obálka',
|
|
195
|
+
'/doc/documentation-ui' => 'Browsing API documentation'
|
|
196
|
+
}.each do |path, heading|
|
|
197
|
+
response = result.fetch('translated').fetch(path)
|
|
198
|
+
expect(response.fetch('status')).to eq(200), "Packaged Czech route failed: #{path}"
|
|
199
|
+
expect(response.fetch('body')).to include('lang="cs"', heading)
|
|
200
|
+
end
|
|
201
|
+
expect(result.fetch('translated').fetch('/doc/documentation-ui').fetch('body')).to include('lang="en"')
|
|
143
202
|
%w[/doc /doc/index /doc/index.md /doc/readme].each do |path|
|
|
144
203
|
body = result.fetch('responses').fetch(path).fetch('body')
|
|
145
204
|
expect(body).to include('<title>HaveAPI internals · ', 'Server framework features',
|
|
@@ -344,7 +344,7 @@ RSpec.describe HaveAPI::PerformanceCI do
|
|
|
344
344
|
%w[flake.lock Gemfile Makefile .ruby-version servers/ruby/benchmarks/endpoints.rb
|
|
345
345
|
servers/ruby/benchmarks/Gemfile servers/ruby/benchmarks/Gemfile.lock servers/ruby/benchmarks/shell.nix
|
|
346
346
|
servers/ruby/test_support/performance_sqlite_fixture.rb clients/ruby/Gemfile clients/rust/Gemfile
|
|
347
|
-
doc/performance.md utils/performance_ci.rb .github/workflows/servers-ruby-performance.yml
|
|
347
|
+
doc/en/performance.md utils/performance_ci.rb .github/workflows/servers-ruby-performance.yml
|
|
348
348
|
servers/ruby/benchmarks/spec/client_examples_spec.rb servers/ruby/test_support/all_client_performance_fixture.rb
|
|
349
349
|
clients/go/lib/haveapi/go_client/documentation.rb clients/typescript/lib/haveapi/typescript_client/documentation.rb
|
|
350
350
|
clients/js/src/client.ts clients/python/haveapi/client.py clients/php/src/Client.php clients/new-client/renderer.rb].each do |path|
|
|
@@ -10,6 +10,8 @@ require_relative 'support/samples'
|
|
|
10
10
|
describe HaveAPI::PerformanceCI::Campaign do
|
|
11
11
|
let(:root) { File.expand_path('../../../..', __dir__) }
|
|
12
12
|
let(:error) { HaveAPI::Performance::ContractError }
|
|
13
|
+
let(:shallow_files) { " s.files = `git ls-files -z`.split(\"\\x0\") + Dir.glob('doc/*')\n" }
|
|
14
|
+
let(:recursive_files) { " s.files = `git ls-files -z`.split(\"\\x0\") + Dir.glob('doc/**/*').select { |path| File.file?(path) }\n" }
|
|
13
15
|
|
|
14
16
|
before do
|
|
15
17
|
# These metadata fixtures evaluate real gemspecs without loading the optional
|
|
@@ -44,6 +46,12 @@ describe HaveAPI::PerformanceCI::Campaign do
|
|
|
44
46
|
end
|
|
45
47
|
end
|
|
46
48
|
|
|
49
|
+
def with_files(contents, statement)
|
|
50
|
+
path = 'servers/ruby/haveapi.gemspec'
|
|
51
|
+
previous = contents.fetch(path).lines.find { |line| line.start_with?(' s.files ') }
|
|
52
|
+
contents.merge(path => contents.fetch(path).sub(previous, statement))
|
|
53
|
+
end
|
|
54
|
+
|
|
47
55
|
def prepare(baseline, candidate)
|
|
48
56
|
Dir.mktmpdir('haveapi-own-versions-') do |directory|
|
|
49
57
|
roots = { baseline: File.join(directory, 'baseline'), candidate: File.join(directory, 'candidate') }
|
|
@@ -82,11 +90,12 @@ describe HaveAPI::PerformanceCI::Campaign do
|
|
|
82
90
|
end
|
|
83
91
|
end
|
|
84
92
|
|
|
85
|
-
def replay_samples(baseline = '0.31.0')
|
|
93
|
+
def replay_samples(baseline = '0.31.0', selections: {}, normalize_files: true)
|
|
86
94
|
samples, budgets = PerformanceSamples.fixture
|
|
87
95
|
samples.fetch('sources').each do |role, source|
|
|
88
96
|
contents = source_contents(role == 'baseline' ? baseline : '0.31.1').slice(*HaveAPI::Performance::SourceVersions::PATHS)
|
|
89
|
-
|
|
97
|
+
contents = with_files(contents, selections.fetch(role)) if selections.has_key?(role)
|
|
98
|
+
receipt = HaveAPI::Performance::SourceVersions.capture(contents, normalize_files:)
|
|
90
99
|
source['files_sha256'].merge!(receipt.fetch('raw_sha256'))
|
|
91
100
|
samples.fetch('observations').each_value do |observation|
|
|
92
101
|
next unless observation.fetch('source').fetch('root') == source.fetch('root')
|
|
@@ -165,4 +174,104 @@ describe HaveAPI::PerformanceCI::Campaign do
|
|
|
165
174
|
samples, budgets = PerformanceSamples.fixture
|
|
166
175
|
expect(compare(samples, JSON.parse(budgets)).fetch('status')).to eq('pass')
|
|
167
176
|
end
|
|
177
|
+
|
|
178
|
+
it 'accepts only the reviewed packaging transition in preparation and live input capture' do
|
|
179
|
+
contents = { baseline: with_files(source_contents('0.31.1'), shallow_files),
|
|
180
|
+
candidate: with_files(source_contents('0.31.1'), recursive_files) }
|
|
181
|
+
prepare(contents[:baseline], contents[:candidate]) do |roots|
|
|
182
|
+
retained = JSON.parse(File.read(File.join(File.dirname(roots[:baseline]), 'dependency-compatibility.json')))
|
|
183
|
+
expect(retained['baseline']['gemspecs']).to eq(retained['candidate']['gemspecs'])
|
|
184
|
+
receipts = retained.values.map { |input| input.fetch('source_versions') }
|
|
185
|
+
expect(receipts.first.fetch('raw_sha256')).not_to eq(receipts.last.fetch('raw_sha256'))
|
|
186
|
+
expect(receipts.first.fetch('normalized_sha256')).to eq(receipts.last.fetch('normalized_sha256'))
|
|
187
|
+
expect(receipts.map { |receipt| receipt.fetch('file_selection') }).to eq(%w[documentation-files-v1 documentation-files-v1])
|
|
188
|
+
|
|
189
|
+
graphs = roots.map do |role, directory|
|
|
190
|
+
%w[HaveAPI::VERSION HaveAPI::Client::VERSION HaveAPI::RustClient::VERSION].each { |constant| stub_const(constant, '0.31.1') }
|
|
191
|
+
inputs = JSON.parse(JSON.generate(HaveAPI::Performance::Worker.inputs(directory, 'quick', benchmark: true)))
|
|
192
|
+
hashes = contents.fetch(role).transform_values { |text| Digest::SHA256.hexdigest(text) }
|
|
193
|
+
expect(inputs.fetch('source_versions')).to eq(retained.fetch(role.to_s).fetch('source_versions'))
|
|
194
|
+
expect do
|
|
195
|
+
HaveAPI::Performance.validate_input_receipts(inputs, { 'files_sha256' => hashes }, profile: 'quick', lineage: nil)
|
|
196
|
+
end.not_to raise_error
|
|
197
|
+
HaveAPI::Performance::Release.graph(inputs)
|
|
198
|
+
end
|
|
199
|
+
expect(graphs.first).to eq(graphs.last)
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
it 'replays the exact old/new packaging pair while retaining raw source hashes' do
|
|
204
|
+
samples, budgets = replay_samples('0.31.1', selections: { 'baseline' => shallow_files, 'candidate' => recursive_files })
|
|
205
|
+
|
|
206
|
+
expect(compare(samples, budgets).fetch('status')).to eq('pass')
|
|
207
|
+
path = 'servers/ruby/haveapi.gemspec'
|
|
208
|
+
expect(samples['sources']['baseline']['files_sha256'][path]).not_to eq(samples['sources']['candidate']['files_sha256'][path])
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
it 'keeps all bytes outside the exact packaging statement and evaluated requirements strict' do
|
|
212
|
+
original = with_files(source_contents('0.31.0'), shallow_files)
|
|
213
|
+
candidate = with_files(source_contents('0.31.1'), recursive_files)
|
|
214
|
+
path = 'servers/ruby/haveapi.gemspec'
|
|
215
|
+
changes = [
|
|
216
|
+
candidate.merge(path => candidate.fetch(path).sub('Framework for creating', 'Framework for describing')),
|
|
217
|
+
candidate.merge(path => candidate.fetch(path).sub("'activesupport', '>= 7.1'", "'activesupport', '>= 7.0'")),
|
|
218
|
+
candidate.merge(path => "#{candidate.fetch(path)}\n# unrelated comment\n"),
|
|
219
|
+
candidate.merge('.ruby-version' => "3.2.1\n")
|
|
220
|
+
]
|
|
221
|
+
changes.each do |changed|
|
|
222
|
+
expect { prepare(original, changed) }.to raise_error(HaveAPI::PerformanceCI::Error, /Dependency inputs differ/)
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
it 'does not normalize unknown, absent, duplicated or modified file statements' do
|
|
227
|
+
contents = source_contents('0.31.1').slice(*HaveAPI::Performance::SourceVersions::PATHS)
|
|
228
|
+
expected = HaveAPI::Performance::SourceVersions.capture(with_files(contents, shallow_files)).fetch('normalized_sha256')
|
|
229
|
+
variants = [
|
|
230
|
+
recursive_files.sub('doc/**/*', 'doc/**'), recursive_files.sub('File.file?', 'File.symlink?'),
|
|
231
|
+
recursive_files.sub("\n", " # additional behavior\n"), '', shallow_files + recursive_files,
|
|
232
|
+
"#{recursive_files} s.files = []\n"
|
|
233
|
+
]
|
|
234
|
+
variants.each do |statement|
|
|
235
|
+
changed = with_files(contents, statement)
|
|
236
|
+
receipt = HaveAPI::Performance::SourceVersions.capture(changed)
|
|
237
|
+
expect(receipt).not_to have_key('file_selection')
|
|
238
|
+
expect(receipt.fetch('normalized_sha256')).not_to eq(expected)
|
|
239
|
+
expect(receipt).to eq(HaveAPI::Performance::SourceVersions.capture(changed, normalize_files: false))
|
|
240
|
+
end
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
it 'rejects tampered or stripped packaging markers and source bindings on replay' do
|
|
244
|
+
%w[marker stripped added raw normalized content source manifest].each do |fault|
|
|
245
|
+
selections = fault == 'added' ? {} : { 'baseline' => shallow_files, 'candidate' => recursive_files }
|
|
246
|
+
samples, budgets = replay_samples(selections:, normalize_files: fault != 'added')
|
|
247
|
+
inputs = samples['observations']['candidate']['inputs']
|
|
248
|
+
receipt = inputs.fetch('source_versions')
|
|
249
|
+
path = 'servers/ruby/haveapi.gemspec'
|
|
250
|
+
case fault
|
|
251
|
+
when 'marker' then receipt['file_selection'] = 'unreviewed-policy'
|
|
252
|
+
when 'stripped' then receipt.delete('file_selection')
|
|
253
|
+
when 'added' then receipt['file_selection'] = 'documentation-files-v1'
|
|
254
|
+
when 'raw' then receipt['raw_sha256'][path] = 'f' * 64
|
|
255
|
+
when 'normalized' then receipt['normalized_sha256'][path] = 'f' * 64
|
|
256
|
+
when 'content' then receipt['contents'][path] += "# changed\n"
|
|
257
|
+
when 'source' then samples['sources']['candidate']['files_sha256'][path] = 'f' * 64
|
|
258
|
+
when 'manifest' then inputs['manifests'][path] = 'f' * 64
|
|
259
|
+
end
|
|
260
|
+
expect { compare(samples, budgets) }.to raise_error(error), fault
|
|
261
|
+
end
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
it 'continues to replay legacy own-version receipts with raw file selection' do
|
|
265
|
+
samples, budgets = replay_samples(normalize_files: false)
|
|
266
|
+
|
|
267
|
+
expect(compare(samples, budgets).fetch('status')).to eq('pass')
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
it 'leaves the historical maintenance packaging comparison strict' do
|
|
271
|
+
contents = source_contents('0.30.1')
|
|
272
|
+
old = HaveAPI::Performance::Release.capture(with_files(contents, shallow_files))
|
|
273
|
+
new = HaveAPI::Performance::Release.capture(with_files(contents, recursive_files))
|
|
274
|
+
|
|
275
|
+
expect(old.fetch('normalized_sha256')).not_to eq(new.fetch('normalized_sha256'))
|
|
276
|
+
end
|
|
168
277
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: haveapi
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.32.
|
|
4
|
+
version: 0.32.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jakub Skokan
|
|
@@ -29,14 +29,14 @@ dependencies:
|
|
|
29
29
|
requirements:
|
|
30
30
|
- - "~>"
|
|
31
31
|
- !ruby/object:Gem::Version
|
|
32
|
-
version: 0.32.
|
|
32
|
+
version: 0.32.2
|
|
33
33
|
type: :runtime
|
|
34
34
|
prerelease: false
|
|
35
35
|
version_requirements: !ruby/object:Gem::Requirement
|
|
36
36
|
requirements:
|
|
37
37
|
- - "~>"
|
|
38
38
|
- !ruby/object:Gem::Version
|
|
39
|
-
version: 0.32.
|
|
39
|
+
version: 0.32.2
|
|
40
40
|
- !ruby/object:Gem::Dependency
|
|
41
41
|
name: i18n
|
|
42
42
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -218,17 +218,24 @@ files:
|
|
|
218
218
|
- benchmarks/performance_compare.rb
|
|
219
219
|
- benchmarks/shell.nix
|
|
220
220
|
- benchmarks/spec/client_examples_spec.rb
|
|
221
|
-
- doc/client-examples.md
|
|
222
|
-
- doc/create-client.md
|
|
223
|
-
- doc/
|
|
224
|
-
- doc/
|
|
221
|
+
- doc/cs/client-examples.md
|
|
222
|
+
- doc/cs/create-client.md
|
|
223
|
+
- doc/cs/json-schema.html
|
|
224
|
+
- doc/cs/protocol.md
|
|
225
|
+
- doc/cs/readme.md
|
|
226
|
+
- doc/cs/typed-input-validation.md
|
|
227
|
+
- doc/en/client-examples.md
|
|
228
|
+
- doc/en/create-client.md
|
|
229
|
+
- doc/en/documentation-oauth.md
|
|
230
|
+
- doc/en/documentation-ui.md
|
|
231
|
+
- doc/en/json-schema.html
|
|
232
|
+
- doc/en/performance.md
|
|
233
|
+
- doc/en/protocol.md
|
|
234
|
+
- doc/en/readme.md
|
|
235
|
+
- doc/en/typed-input-validation.md
|
|
225
236
|
- doc/hooks.erb
|
|
226
237
|
- doc/index.md
|
|
227
|
-
- doc/json-schema.html
|
|
228
|
-
- doc/performance.md
|
|
229
|
-
- doc/protocol.md
|
|
230
238
|
- doc/protocol.png
|
|
231
|
-
- doc/typed-input-validation.md
|
|
232
239
|
- haveapi.gemspec
|
|
233
240
|
- lib/haveapi.rb
|
|
234
241
|
- lib/haveapi/action.rb
|
|
@@ -271,6 +278,7 @@ files:
|
|
|
271
278
|
- lib/haveapi/documentation_clients.rb
|
|
272
279
|
- lib/haveapi/documentation_context.rb
|
|
273
280
|
- lib/haveapi/documentation_helpers.rb
|
|
281
|
+
- lib/haveapi/documentation_locale.rb
|
|
274
282
|
- lib/haveapi/documentation_oauth.rb
|
|
275
283
|
- lib/haveapi/documentation_schema.rb
|
|
276
284
|
- lib/haveapi/documentation_search.rb
|
|
@@ -381,6 +389,8 @@ files:
|
|
|
381
389
|
- spec/client_examples/assets/documentation_test.cjs
|
|
382
390
|
- spec/client_examples/assets/highlighter_test.cjs
|
|
383
391
|
- spec/client_examples/assets/tabs_test.cjs
|
|
392
|
+
- spec/client_examples/comment_capture.rb
|
|
393
|
+
- spec/client_examples/comments_spec.rb
|
|
384
394
|
- spec/client_examples/context_performance_spec.rb
|
|
385
395
|
- spec/client_examples/context_spec.rb
|
|
386
396
|
- spec/client_examples/detail_spec.rb
|
|
@@ -408,12 +418,15 @@ files:
|
|
|
408
418
|
- spec/documentation/client_examples_spec.rb
|
|
409
419
|
- spec/documentation/client_overview_spec.rb
|
|
410
420
|
- spec/documentation/current_user_html_escaping_spec.rb
|
|
421
|
+
- spec/documentation/example_selection_spec.rb
|
|
411
422
|
- spec/documentation/example_variants_spec.rb
|
|
412
423
|
- spec/documentation/examples_spec.rb
|
|
413
424
|
- spec/documentation/fixtures/search_index.json
|
|
414
425
|
- spec/documentation/host_html_escaping_spec.rb
|
|
415
426
|
- spec/documentation/identity_and_guides_spec.rb
|
|
416
427
|
- spec/documentation/identity_context_spec.rb
|
|
428
|
+
- spec/documentation/language_settings_spec.rb
|
|
429
|
+
- spec/documentation/locale_spec.rb
|
|
417
430
|
- spec/documentation/navigation_spec.rb
|
|
418
431
|
- spec/documentation/oauth_fixture_spec.rb
|
|
419
432
|
- spec/documentation/oauth_spec.rb
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|