Feature #44425 » 0003-parse-error-to-flash-error-message.patch
| app/javascript/controllers/mermaid_controller.js | ||
|---|---|---|
| 67 | 67 |
container.textContent = this.element.textContent.trim(); |
| 68 | 68 |
(pre || this.element).insertAdjacentElement('afterend', container);
|
| 69 | 69 | |
| 70 |
// mermaid.js draws its own error diagram on failure, so the code block is replaced either way. |
|
| 71 |
// The rejection is left for the browser to report. |
|
| 72 |
mermaid.run({ nodes: [container], suppressErrors: false }).finally(() => {
|
|
| 70 |
// mermaid.js draws its own error diagram on failure |
|
| 71 |
// replace it with a redmine flash message while keeping the source block available |
|
| 72 |
// so the invalid diagram can be inspected and copied |
|
| 73 |
mermaid.run({ nodes: [container], suppressErrors: false }).then(() => {
|
|
| 73 | 74 |
if (pre) pre.style.display = 'none'; |
| 75 |
}).catch((error) => {
|
|
| 76 |
container.remove(); |
|
| 77 | ||
| 78 |
const errorElement = document.createElement('div');
|
|
| 79 |
errorElement.className = 'flash error'; |
|
| 80 |
errorElement.innerHTML = '<p>Failed to render mermaid diagram:</p>'; |
|
| 81 | ||
| 82 |
const message = document.createElement('p');
|
|
| 83 |
message.textContent = error?.message || String(error); |
|
| 84 | ||
| 85 |
errorElement.appendChild(message); |
|
| 86 | ||
| 87 |
const wrapper = pre.closest('.pre-wrapper');
|
|
| 88 |
if (wrapper) {
|
|
| 89 |
wrapper.insertAdjacentElement('beforebegin', errorElement);
|
|
| 90 |
} |
|
| 74 | 91 |
}); |
| 75 | 92 |
} |
| 76 | 93 |
} |
| test/system/mermaid_rendering_test.rb | ||
|---|---|---|
| 58 | 58 |
assert_not_equal 'none', page.evaluate_script("getComputedStyle(document.querySelector('div.mermaid svg')).display")
|
| 59 | 59 |
page.driver.browser.execute_cdp('Emulation.setEmulatedMedia', media: '')
|
| 60 | 60 | |
| 61 |
# An invalid diagram renders mermaid.js's own error diagram, |
|
| 62 |
# which replaces the code block just like a successful one does. |
|
| 61 |
assert_selector '#header' |
|
| 62 |
assert_selector '#content' |
|
| 63 |
ensure |
|
| 64 |
page.driver.browser.execute_cdp('Emulation.setEmulatedMedia', media: '')
|
|
| 65 |
end |
|
| 66 | ||
| 67 |
def test_should_show_flash_message_for_invalid_mermaid_diagram |
|
| 68 |
issue = Issue.find(1) |
|
| 63 | 69 |
issue.update_column(:description, "```mermaid\nthis is not a valid mermaid diagram(((\n```") |
| 70 | ||
| 71 |
log_user('jsmith', 'jsmith')
|
|
| 64 | 72 |
visit "/issues/#{issue.id}"
|
| 65 | 73 | |
| 66 | 74 |
within('div.description') do
|
| 67 |
assert_selector 'div.mermaid svg .error-icon'
|
|
| 68 |
assert_selector 'code[data-controller=mermaid]', visible: :all
|
|
| 69 |
assert_no_selector 'code[data-controller=mermaid]'
|
|
| 75 |
assert_selector '.flash.error', text: 'Failed to render mermaid diagram'
|
|
| 76 |
assert_selector 'pre'
|
|
| 77 |
assert_no_selector 'div.mermaid svg'
|
|
| 70 | 78 |
end |
| 71 |
assert_selector '#header' |
|
| 72 |
assert_selector '#content' |
|
| 73 |
ensure |
|
| 74 |
page.driver.browser.execute_cdp('Emulation.setEmulatedMedia', media: '')
|
|
| 75 | 79 |
end |
| 76 | 80 | |
| 77 | 81 |
def test_should_render_mermaid_in_description_preview |