feat(ui): wire Logo native loading progress
This commit is contained in:
@@ -7,6 +7,7 @@ import { EventEmitter } from 'node:events';
|
||||
|
||||
class Sprite {}
|
||||
class UITransform {}
|
||||
class ProgressBar { progress = 0; }
|
||||
class Label { string = ''; }
|
||||
class Node extends EventEmitter {
|
||||
static EventType = { TOUCH_END: 'touch-end' };
|
||||
@@ -84,6 +85,53 @@ test('frame request is one shot and real cancellation removes pending draw callb
|
||||
assert.equal(director.listenerCount('draw'), 0);
|
||||
});
|
||||
|
||||
test('asset load task reports validated native loader progress from zero through completion', async () => {
|
||||
const { createAssetLoadTask } = load();
|
||||
const progress: number[] = [];
|
||||
let onProgress!: (completed: number, total: number) => void;
|
||||
let onComplete!: (error: unknown, asset?: unknown) => void;
|
||||
const task = createAssetLoadTask((progressCallback: typeof onProgress, completeCallback: typeof onComplete) => {
|
||||
onProgress = progressCallback; onComplete = completeCallback;
|
||||
}, (value: number) => progress.push(value));
|
||||
|
||||
assert.deepEqual(progress, [0]);
|
||||
onProgress(1, 2); onProgress(2, 2); onComplete(null, { uuid: 'login' });
|
||||
assert.deepEqual(progress, [0, 0.5, 1]);
|
||||
assert.deepEqual(await task.promise, { uuid: 'login' });
|
||||
});
|
||||
|
||||
test('asset load task rejects invalid counts and loader failures without reporting guessed progress', async () => {
|
||||
const { createAssetLoadTask } = load();
|
||||
for (const invalid of [[0, 0], [-1, 2], [3, 2], [0.5, 2], [1, Number.NaN]]) {
|
||||
const progress: number[] = [];
|
||||
let onProgress!: (completed: number, total: number) => void;
|
||||
const task = createAssetLoadTask((progressCallback: typeof onProgress) => { onProgress = progressCallback; },
|
||||
(value: number) => progress.push(value));
|
||||
onProgress(invalid[0], invalid[1]);
|
||||
await assert.rejects(task.promise, /asset load progress/i);
|
||||
assert.deepEqual(progress, [0]);
|
||||
}
|
||||
|
||||
let complete!: (error: unknown, asset?: unknown) => void;
|
||||
const failed = createAssetLoadTask((_progress: unknown, callback: typeof complete) => { complete = callback; }, () => {});
|
||||
complete(new Error('decoder failed'));
|
||||
await assert.rejects(failed.promise, /decoder failed/);
|
||||
});
|
||||
|
||||
test('asset load task cancellation settles pending work and ignores late loader callbacks', async () => {
|
||||
const { createAssetLoadTask } = load();
|
||||
const progress: number[] = [];
|
||||
let onProgress!: (completed: number, total: number) => void;
|
||||
let onComplete!: (error: unknown, asset?: unknown) => void;
|
||||
const task = createAssetLoadTask((progressCallback: typeof onProgress, completeCallback: typeof onComplete) => {
|
||||
onProgress = progressCallback; onComplete = completeCallback;
|
||||
}, (value: number) => progress.push(value));
|
||||
task.cancel();
|
||||
await assert.rejects(task.promise, /cancelled/i);
|
||||
onProgress(1, 2); onComplete(null, { uuid: 'late' });
|
||||
assert.deepEqual(progress, [0]);
|
||||
});
|
||||
|
||||
test('failure display preserves nested server and cleanup errors', () => {
|
||||
const { CocosLocalLoginView } = load(); const f = fixture();
|
||||
const view = new CocosLocalLoginView(f.refs);
|
||||
@@ -116,14 +164,14 @@ test('component rejects non-debug/native before creating host or writing browser
|
||||
}
|
||||
});
|
||||
|
||||
test('component stop cancels pending draw and timer work and disables spinner updates', async () => {
|
||||
test('component stop cancels pending draw and timer work', async () => {
|
||||
const path = new URL('../../YouleNexus/assets/scripts/local-platform-login/LocalPlatformLogin.ts', import.meta.url);
|
||||
const exports: any = {}; const timers = new Map<number, () => void>(); let timerId = 0;
|
||||
runInNewContext(ts.transpileModule(readFileSync(path, 'utf8'), {
|
||||
compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2020, experimentalDecorators: true },
|
||||
}).outputText, { exports, require: (name: string) => {
|
||||
if (name === 'cc/env') return { DEBUG: true };
|
||||
if (name === 'cc') return { Component: class {}, Node, Label, Prefab: class {}, sys: { isNative: false },
|
||||
if (name === 'cc') return { Component: class {}, Node, Label, Prefab: class {}, ProgressBar, sys: { isNative: false },
|
||||
_decorator: { ccclass: () => (target: unknown) => target, property: () => () => {} } };
|
||||
if (name.endsWith('local-login-host.ts')) return {};
|
||||
if (name.endsWith('local-login-view.ts')) return load();
|
||||
@@ -136,10 +184,7 @@ test('component stop cancels pending draw and timer work and disables spinner up
|
||||
const component = new exports.LocalPlatformLogin();
|
||||
const draw = component.nextDraw(); const timer = component.delay(900);
|
||||
const drawRejection = assert.rejects(draw, /cancelled/); const timerRejection = assert.rejects(timer, /cancelled/);
|
||||
component.spinner = { angle: 50, activeInHierarchy: true };
|
||||
component.update(0.5); assert.equal(component.spinner.angle, -40);
|
||||
component.stop(); await Promise.all([drawRejection, timerRejection]);
|
||||
component.update(0.5); assert.equal(component.spinner.angle, -40);
|
||||
assert.equal(timers.size, 0); assert.equal(director.listenerCount('draw'), 0);
|
||||
assert.equal(component.getDiagnostics().pendingCount, 0);
|
||||
});
|
||||
@@ -152,7 +197,7 @@ test('minimum display ignores an early timer wake and cancellation clears its re
|
||||
compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2020, experimentalDecorators: true },
|
||||
}).outputText, { exports, require: (name: string) => {
|
||||
if (name === 'cc/env') return { DEBUG: true };
|
||||
if (name === 'cc') return { Component: class {}, Node, Label, Sprite, UITransform, Prefab: class {}, sys: { isNative: false },
|
||||
if (name === 'cc') return { Component: class {}, Node, Label, Sprite, UITransform, ProgressBar, Prefab: class {}, sys: { isNative: false },
|
||||
_decorator: { ccclass: () => (target: unknown) => target, property: () => () => {} } };
|
||||
if (name.endsWith('local-login-host.ts')) return { createLocalLoginHost: (options: unknown) => {
|
||||
hostOptions = options; return { start: async () => {}, stop() {}, getSnapshot: () => ({}) };
|
||||
@@ -168,10 +213,10 @@ test('minimum display ignores an early timer wake and cancellation clears its re
|
||||
async function started() {
|
||||
const component = new exports.LocalPlatformLogin(); const f = fixture();
|
||||
Object.assign(component, f.refs, { stopButton: new Node(), loadingPrefab: {}, loginPrefab: {} });
|
||||
const loading = new Node('Layer614_Loading'); const group = new Node('group-40');
|
||||
const spinner = new Node('载入动画'); spinner.components.set(Sprite, new Sprite());
|
||||
spinner.components.set(UITransform, new UITransform()); group.children.push(spinner);
|
||||
loading.children.push(group); component.loadingRoot.children.push(loading);
|
||||
const logo = new Node('Layer1_Logo'); const group = new Node('group-1');
|
||||
const bar = new Node('Spirit254'); bar.components.set(ProgressBar, new ProgressBar());
|
||||
group.children.push(bar, new Node('Spirit3103'), new Node('Spirit3104'));
|
||||
logo.children.push(group, new Node('group-32')); component.loadingRoot.children.push(logo);
|
||||
component.loadingRoot.getComponentsInChildren = () => [];
|
||||
await component.start(); director.emit('draw'); await Promise.resolve();
|
||||
return component;
|
||||
|
||||
Reference in New Issue
Block a user