feat: persist incremental live channel analysis
Persist live channel language metadata across background projection rebuilds and target Local AI identity analysis to newly detected streams unless a manual full analysis is requested. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -141,12 +141,12 @@ test('Settings renders Laya batch progress and removes misleading values when it
|
||||
assert.equal(bar.style.width, '');
|
||||
});
|
||||
|
||||
test('analysis remains visibly busy while Laya language batches run after projection completes', async () => {
|
||||
test('analysis completion reloads the persisted projection', async () => {
|
||||
const { window } = createDom();
|
||||
let rebuildClicked = false;
|
||||
let languageRefreshStarted = false;
|
||||
let releaseLanguageRefresh;
|
||||
const languageRefresh = new Promise(resolve => { releaseLanguageRefresh = resolve; });
|
||||
let projectionReloadStarted = false;
|
||||
let releaseProjectionReload;
|
||||
const projectionReload = new Promise(resolve => { releaseProjectionReload = resolve; });
|
||||
window.API = {
|
||||
live: {
|
||||
getProjectionStatus: async () => rebuildClicked
|
||||
@ -176,11 +176,11 @@ test('analysis remains visibly busy while Laya language batches run after projec
|
||||
saveSettings() {}
|
||||
},
|
||||
channelList: {
|
||||
loadChannels: async () => {},
|
||||
refreshLayaLanguages: async () => {
|
||||
languageRefreshStarted = true;
|
||||
await languageRefresh;
|
||||
}
|
||||
loadChannels: async () => {
|
||||
projectionReloadStarted = true;
|
||||
await projectionReload;
|
||||
},
|
||||
refreshLayaLanguages: async () => assert.fail('Browser-side Laya refresh must not run')
|
||||
}
|
||||
};
|
||||
window.app = app;
|
||||
@ -193,28 +193,19 @@ test('analysis remains visibly busy while Laya language batches run after projec
|
||||
window.document.getElementById('live-analysis-button').click();
|
||||
|
||||
try {
|
||||
await waitFor(() => languageRefreshStarted, 'Expected Laya language refresh to start after projection completion');
|
||||
assert.notEqual(window.document.getElementById('live-analysis-status').textContent, 'Analysis complete');
|
||||
assert.equal(window.document.getElementById('live-analysis-progress').hidden, false);
|
||||
await waitFor(() => projectionReloadStarted, 'Expected persisted projection reload after analysis completion');
|
||||
assert.equal(window.document.getElementById('live-analysis-status').textContent, 'Analysis complete');
|
||||
} finally {
|
||||
releaseLanguageRefresh();
|
||||
releaseProjectionReload();
|
||||
window.clearInterval(settingsPage.liveAnalysisPollTimer);
|
||||
}
|
||||
});
|
||||
|
||||
test('user analysis click keeps visible channels after Local AI language failure', async () => {
|
||||
test('user analysis click reloads persisted languages without a browser-side Laya batch', async () => {
|
||||
const { window } = createDom();
|
||||
let rebuildClicked = 0;
|
||||
let layaBatchCalls = 0;
|
||||
let channelLoads = 0;
|
||||
const consoleWarnings = [];
|
||||
window.console = {
|
||||
...console,
|
||||
warn: (...args) => {
|
||||
consoleWarnings.push(args.join(' '));
|
||||
console.warn(...args);
|
||||
}
|
||||
};
|
||||
window.API = {
|
||||
live: {
|
||||
getChannels: async () => {
|
||||
@ -269,26 +260,22 @@ test('user analysis click keeps visible channels after Local AI language failure
|
||||
window.clearInterval(channelList._epgRefreshTimer);
|
||||
window.clearInterval(settingsPage.liveAnalysisPollTimer);
|
||||
|
||||
const notice = window.document.querySelector('.laya-language-notice');
|
||||
const afterNames = [...window.document.querySelectorAll('.channel-name')].map(item => item.textContent);
|
||||
const languageBadges = [...window.document.querySelectorAll('.variant-language')].map(item => item.textContent);
|
||||
const groupNames = [...window.document.querySelectorAll('.group-name')].map(item => item.textContent);
|
||||
|
||||
assert.equal(channelLoads, 2);
|
||||
assert.equal(layaBatchCalls, 1);
|
||||
assert.ok(notice);
|
||||
assert.match(notice.textContent, /Local AI language detection failed/);
|
||||
assert.equal(layaBatchCalls, 0);
|
||||
assert.deepEqual(afterNames, ['Sports One', 'Sports One']);
|
||||
assert.deepEqual([...new Set(languageBadges)].sort(), ['EN 100%', 'FR 100%']);
|
||||
assert.deepEqual(groupNames, ['Favorites', 'Sports France']);
|
||||
assert.equal(window.document.querySelector('.empty-state'), null);
|
||||
assert.equal(window.document.querySelector('#channel-list > .loading'), null);
|
||||
assert.equal(channelList.languageDetectionFallback, true);
|
||||
assert.equal(channelList.languageDetectionFallback, false);
|
||||
assert.equal(channelList.logicalChannels[0].variants.length, 2);
|
||||
assert.ok(consoleWarnings.some(line => line.includes('Local AI language detection unavailable')));
|
||||
});
|
||||
|
||||
test('successful Standard fallback after Local AI failure keeps channels and reports the AI failure', async () => {
|
||||
test('hybrid analysis completion relies on persisted projection without Standard browser fallback', async () => {
|
||||
const { window } = createDom();
|
||||
let rebuildClicked = 0;
|
||||
let layaBatchCalls = 0;
|
||||
@ -345,16 +332,13 @@ test('successful Standard fallback after Local AI failure keeps channels and rep
|
||||
window.clearInterval(settingsPage.liveAnalysisPollTimer);
|
||||
|
||||
const afterNames = [...window.document.querySelectorAll('.channel-name')].map(item => item.textContent);
|
||||
const notice = window.document.querySelector('.laya-language-notice');
|
||||
|
||||
assert.equal(layaBatchCalls, 1);
|
||||
assert.equal(layaBatchCalls, 0);
|
||||
assert.deepEqual(afterNames, ['Sports One', 'Sports One']);
|
||||
assert.equal(window.document.querySelector('.empty-state'), null);
|
||||
assert.equal(window.document.querySelector('#channel-list > .loading'), null);
|
||||
assert.ok(notice);
|
||||
assert.match(notice.textContent, /Local AI language detection failed/);
|
||||
assert.match(notice.textContent, /Standard matching/);
|
||||
assert.equal(channelList.languageDetectionFallback, true);
|
||||
assert.equal(window.document.querySelector('.laya-language-notice'), null);
|
||||
assert.equal(channelList.languageDetectionFallback, false);
|
||||
});
|
||||
|
||||
test('successful Laya language batch updates visible variant languages without Standard fallback', async () => {
|
||||
|
||||
Reference in New Issue
Block a user