diff --git a/site/app.js b/site/app.js index 8ecd528..9aa0fc7 100644 --- a/site/app.js +++ b/site/app.js @@ -983,7 +983,7 @@ function resetComponentsForTarget() { setComponentMessage(''); } renderComponentChoices(); - updateBuildRequest(); + return updateBuildRequest(); } function setupComponentBuilder(catalog) { @@ -1002,13 +1002,13 @@ function setupComponentBuilder(catalog) { function updateFlavors() { const available = flavorsForTarget(targetSelect.value); populateSelect(flavorSelect, available, available[0].id); - resetComponentsForTarget(); + return resetComponentsForTarget(); } targetSelect.addEventListener('change', updateFlavors); flavorSelect.addEventListener('change', () => updateBuildRequest()); categorySelect.addEventListener('change', renderComponentChoices); document.querySelector('#component-search').addEventListener('input', renderComponentChoices); - updateFlavors(); + return updateFlavors(); } async function loadComponentCatalog() { @@ -1018,7 +1018,7 @@ async function loadComponentCatalog() { if (!response.ok) throw new Error(`HTTP ${response.status}`); const catalog = await response.json(); if (!validateComponentCatalog(catalog)) throw new Error('unexpected component catalog schema'); - setupComponentBuilder(catalog); + await setupComponentBuilder(catalog); status.classList.remove('error'); status.textContent = `组件目录 ${catalog.catalog_version} 已验证 / Catalog verified`; } catch (error) { diff --git a/tests/test_pages_ui.js b/tests/test_pages_ui.js index 021cd0c..f01f53d 100755 --- a/tests/test_pages_ui.js +++ b/tests/test_pages_ui.js @@ -480,10 +480,14 @@ function assertSafeEmptyState() { const componentCatalog = JSON.parse(fs.readFileSync(path.join(root, 'components/catalog.json'), 'utf8')); -async function loadCatalogWith(responseFactory) { +async function loadCatalogWith(responseFactory, cryptoImpl = webcrypto) { context.fetch = responseFactory; - await loadComponentCatalog(); - await new Promise((resolve) => setTimeout(resolve, 20)); + context.crypto = cryptoImpl; + try { + await loadComponentCatalog(); + } finally { + context.crypto = webcrypto; + } } function flattenChildren(element) { @@ -522,12 +526,20 @@ function flattenChildren(element) { const normalized = normalizedBuildRequest(componentCatalog, 'official', dependencySelection, normalizedHash); assert.match(actionsInputs(normalized), /^target=x86_64\nflavor=official\ncomponents=wireguard\ncatalog_version=2026\.07\.20\nrequest_hash=2aeca1c0914e74fa52c7e7748a5e3870e510a91883b1f647312addf678f966cf$/); + const delayedCrypto = { + subtle: { + async digest(...args) { + await new Promise((resolve) => setTimeout(resolve, 50)); + return webcrypto.subtle.digest(...args); + }, + }, + }; await loadCatalogWith(async (url, options) => { assert.equal(url, 'components/catalog.json'); assert.equal(options.cache, 'no-store'); assert.equal(options.credentials, 'same-origin'); return { ok: true, json: async () => clone(componentCatalog) }; - }); + }, delayedCrypto); assert.equal(document.querySelector('#component-status').classList.contains('error'), false); assert.equal(document.querySelector('#component-target').disabled, false); assert.equal(document.querySelector('#component-target').value, 'x86_64');