fix: keep Apply button disabled during queued resolution and re-enable on failure

This commit is contained in:
Dariusz L
2026-09-10 01:16:31 +02:00
parent e9bc6369a2
commit b93f63e68a
2 changed files with 53 additions and 1 deletions
@@ -1952,6 +1952,55 @@ test('Apply reuses the content-preserving workflow analysis path', () => {
assert.doesNotMatch(applyPendingResolutionList, /refreshAnalysisInBackground\(/);
});
test('Apply stays busy after linking until the old card is removed', async () => {
const applyQueuedByKey = eval(`(${extractMethod(queueMethodsSource, 'applyQueuedByKey')})`);
const window = new Window();
const button = window.document.createElement('button');
button.textContent = 'Apply';
window.document.body.append(button);
let finishApply;
let calls = 0;
const dialog = {
pendingIndex: new Map([['model', 0]]),
pendingResolutions: [{}],
async applyPendingResolutionList() {
calls += 1;
await new Promise(resolve => { finishApply = resolve; });
this.pendingIndex.delete('model');
}
};
const pending = applyQueuedByKey.call(dialog, 'model', button);
assert.equal(button.textContent, 'Applying...');
assert.equal(button.disabled, true);
await applyQueuedByKey.call(dialog, 'model', button);
assert.equal(calls, 1);
finishApply();
await pending;
assert.equal(button.isConnected, true);
assert.equal(button.textContent, 'Applying...');
assert.equal(button.disabled, true);
assert.equal(button.classList.contains('mr-btn-is-disabled'), true);
button.remove();
await window.happyDOM.close();
});
test('Apply becomes available again when linking fails and selection stays queued', async () => {
const applyQueuedByKey = eval(`(${extractMethod(queueMethodsSource, 'applyQueuedByKey')})`);
const window = new Window();
const button = window.document.createElement('button');
window.document.body.append(button);
const dialog = {
pendingIndex: new Map([['model', 0]]),
pendingResolutions: [{}],
async applyPendingResolutionList() { return null; }
};
await applyQueuedByKey.call(dialog, 'model', button);
assert.equal(button.textContent, 'Apply');
assert.equal(button.disabled, false);
assert.equal(button.classList.contains('mr-btn-is-disabled'), false);
await window.happyDOM.close();
});
test('Apply keeps the workflow slot key when resolved path identity changes', () => {
const doesResolvedModelMatchAlias = eval(
`(${extractMethod(queueMethodsSource, 'doesResolvedModelMatchAlias')})`
+4 -1
View File
@@ -2096,6 +2096,7 @@ export const queueMethods = {
* Apply one queued resolution from the selected bar.
*/
async applyQueuedByKey(key, button = null) {
if (button?.disabled) return;
if (!key || !this.pendingIndex.has(key)) {
this.showNotification('Selected match is no longer queued.', 'error');
return;
@@ -2117,7 +2118,9 @@ export const queueMethods = {
try {
await this.applyPendingResolutionList([selection], { clearAll: false });
} finally {
if (button?.isConnected) {
// A successful link removes the selection before the background
// analysis replaces this card. Keep it busy until that render.
if (button?.isConnected && this.pendingIndex.has(key)) {
button.disabled = false;
button.classList.remove('mr-btn-is-disabled');
button.textContent = 'Apply';