Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: work with extremely large results #291

Merged
merged 7 commits into from
Mar 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
20 changes: 15 additions & 5 deletions packages/axe-core-api/e2e/selenium/spec/api_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
require "axe/core"
require "axe/api/run"

options = Selenium::WebDriver::Firefox::Options.new
options.add_argument('--headless')
$driver = Selenium::WebDriver.for :firefox, options: options
options = Selenium::WebDriver::Chrome::Options.new
# options.add_argument('--headless')
$driver = Selenium::WebDriver.for :chrome, options: options

Run = Axe::API::Run

Expand All @@ -20,6 +20,7 @@ def run_axe(run = Run.new)
$axe_post_43x = Axe::Configuration.instance.jslib
$crasher_js = File.read File.join($fixture_root, "axe-crasher.js")
$force_legacy_js = File.read File.join($fixture_root, "axe-force-legacy.js")
$large_partial_js = File.read File.join($fixture_root, "axe-large-partial.js")

def fixture(filename)
"http://localhost:8000" + filename
Expand Down Expand Up @@ -56,7 +57,7 @@ def recursive_compact(thing)
elsif thing.is_a?(Hash)
thing.each_with_object({}) do |(k,v), h|
v = recursive_compact(v)
h[k] = v unless [nil, [], {}].include?(v)
h[k] = v unless ([nil, [], {}].include?(v) or k == :html)
end
else
thing
Expand Down Expand Up @@ -92,7 +93,7 @@ def recursive_compact(thing)
end

describe "frame tests" do
it "injects into nested iframes" do
it "injects into nested iframes", :fo => true do
$driver.get fixture "/nested-iframes.html"
res = run_axe
expect(res.results.violations).not_to be_empty
Expand Down Expand Up @@ -268,6 +269,15 @@ def recursive_compact(thing)
expect { run_axe }.to raise_error /finishRun failed/
}
end

it "works with large results", :nt => true do
$driver.get fixture "/index.html"
res = with_js($axe_post_43x + $large_partial_js) { run_axe }


expect(res.results.passes.length).to eq 1
expect(res.results.passes[0].id).to eq :'duplicate-id'
end
end


Expand Down
26 changes: 22 additions & 4 deletions packages/axe-core-api/lib/axe/api/run.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,19 @@ def analyze_post_43x(page, lib)
partial_results = run_partial_recursive(page, @context, lib, true)
throw partial_results if partial_results.respond_to?("key?") and partial_results.key?("errorMessage")
results = within_about_blank_context(page) { |page|
partial_res_str = partial_results.to_json
size_limit = 20_000_000
while not partial_res_str.empty? do
chunk_size = size_limit
chunk_size = partial_res_str.length if chunk_size > partial_res_str.length
chunk = partial_res_str[0..chunk_size-1]
partial_res_str = partial_res_str[chunk_size..-1]
store_chunk page, chunk
end

Common::Loader.new(page, lib).load_top_level Axe::Configuration.instance.jslib
begin
axe_finish_run page, partial_results
axe_finish_run page
rescue
raise StandardError.new "axe.finishRun failed. Please check out https://github.com/dequelabs/axe-core-gems/blob/develop/error-handling.md"
end
Expand Down Expand Up @@ -138,12 +148,20 @@ def run_partial_recursive(page, context, lib, top_level = false)
return results
end

def axe_finish_run(page, partial_results)
def store_chunk(page, chunk)
script = <<-JS
const chunk = arguments[0];
window.partialResults ??= '';
window.partialResults += chunk;
JS
page.execute_script_fixed script, chunk
end
def axe_finish_run(page)
script = <<-JS
const partialResults = arguments[0];
const partialResults = JSON.parse(window.partialResults || '[]');
return axe.finishRun(partialResults);
JS
page.execute_script_fixed script, partial_results
page.execute_script_fixed script
end

def axe_shadow_select(page, frame_selector)
Expand Down