mirror of
https://github.com/cocos/cocos-engine.git
synced 2026-09-07 00:02:53 +08:00
138 lines
5.0 KiB
TypeScript
138 lines
5.0 KiB
TypeScript
import { ccclass } from 'cc.decorator';
|
|
import { warnID } from '../../cocos/core';
|
|
import { float, property } from '../../cocos/core/data/class-decorator';
|
|
import * as requiringFrame from '../../cocos/core/data/utils/requiring-frame';
|
|
import { getClassName, unregisterClass, _getClassId } from '../../cocos/core/utils/js-typed';
|
|
import { Component } from '../../cocos/core/components/component'
|
|
|
|
/**
|
|
* Happened when:
|
|
* - `@property(undefined)` Explicit `undefined`, it's rare
|
|
* - `@property(${some-global}.${some-property})` From a expression which evaluated as `undefined`,
|
|
* - `@property(${imported-undefined})` Due to circular reference
|
|
*/
|
|
test('explicit undefined type', () => {
|
|
// @ts-ignore
|
|
warnID.mockClear();
|
|
|
|
@ccclass
|
|
class Foo {
|
|
/**
|
|
* `@property(type)` form.
|
|
*/
|
|
@property(undefined)
|
|
public property1 = 0;
|
|
|
|
/**
|
|
* `@property({ type })` form.
|
|
*/
|
|
@property({
|
|
type: undefined,
|
|
})
|
|
public property2 = 0;
|
|
}
|
|
|
|
expect(warnID).toHaveBeenCalledTimes(2);
|
|
expect(warnID).toHaveBeenNthCalledWith(1, 3660, 'property1', Foo.name);
|
|
expect(warnID).toHaveBeenNthCalledWith(2, 3660, 'property2', Foo.name);
|
|
});
|
|
|
|
describe('ccclass warnings', () => {
|
|
const clearWarnID = () => {
|
|
// @ts-expect-error
|
|
warnID.mockClear();
|
|
};
|
|
|
|
test('Warn on no default value specified', () => {
|
|
clearWarnID();
|
|
{ @ccclass class _ { @float p; } }
|
|
expect(warnID).toHaveBeenCalledTimes(1);
|
|
expect(warnID).toHaveBeenCalledWith(3654, '_', 'p');
|
|
|
|
clearWarnID();
|
|
{ @ccclass class _ { @property p; } }
|
|
expect(warnID).toHaveBeenCalledTimes(1);
|
|
expect(warnID).toHaveBeenCalledWith(3654, '_', 'p');
|
|
|
|
clearWarnID();
|
|
@ccclass class C { }
|
|
{ @ccclass class _ { @property(C) p; } }
|
|
expect(warnID).not.toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
describe('Class id & class name', () => {
|
|
type ExpectedNameComeFrom = 'self-name' | 'explicit-name' | 'frame-name';
|
|
type ExpectedIdComeFrom = 'self-name' | 'explicit-name' | 'frame-uuid' | 'temp-id';
|
|
|
|
test.each([
|
|
[true, true, true, 'explicit-name', 'frame-uuid'], // Usually: in user land, components, with explicit name
|
|
[true, true, false, 'explicit-name', 'explicit-name'], // Usually: in user land, non-components, with explicit name
|
|
[true, false, true, 'explicit-name', 'explicit-name'], // Usually: in engine, components
|
|
[true, false, false, 'explicit-name', 'explicit-name'], // Usually: in engine, non-components
|
|
|
|
[false, true, true, 'frame-name', 'frame-uuid'], // Usually: in user land, components, no explicit name
|
|
[false, true, false, 'self-name', 'temp-id'], // Usually: in user land, non-components, no explicit name
|
|
[false, false, true, 'self-name', 'temp-id'],
|
|
[false, false, false, 'self-name', 'temp-id'],
|
|
] as Array<[
|
|
withExplicitName: boolean,
|
|
withinRequiringFrame: boolean,
|
|
inheritingFromComponent: boolean,
|
|
expectedNameComeFrom: ExpectedNameComeFrom,
|
|
expectedIdComeFrom: ExpectedIdComeFrom,
|
|
]>)(
|
|
`WithExplicitName: %j, WithinRequiringFrame: %j, InheritingFromComponent: %j`,
|
|
(withExplicitName, withinRequiringFrame, inheritingFromComponent, expectedNameComeFrom, expectedIdComeFrom) => {
|
|
const EXPLICIT_NAME = '__EXPLICIT_NAME__';
|
|
const FRAME_NAME = '__FRAME_NAME__';
|
|
const FRAME_UUID = '__FRAME_UUID__';
|
|
const expectedName = (() => {
|
|
switch (expectedNameComeFrom) {
|
|
case 'frame-name': return FRAME_NAME;
|
|
case 'explicit-name': return EXPLICIT_NAME;
|
|
default: case 'self-name': return 'Cls';
|
|
}
|
|
})();
|
|
const expectedId = (() => {
|
|
switch (expectedIdComeFrom) {
|
|
case 'frame-uuid': return FRAME_UUID;
|
|
case 'explicit-name': return EXPLICIT_NAME;
|
|
case 'temp-id': return expect.stringMatching(/^TmpCId\.\.[0-9]+/i);
|
|
default: case 'self-name': return 'Cls';
|
|
}
|
|
})();
|
|
|
|
if (withinRequiringFrame) {
|
|
requiringFrame.push(
|
|
{}, // module
|
|
FRAME_UUID, // uuid
|
|
FRAME_NAME, // script
|
|
);
|
|
}
|
|
|
|
let Cls_: Function;
|
|
if (inheritingFromComponent) {
|
|
Cls_ = (() => {
|
|
@(withExplicitName ? ccclass(EXPLICIT_NAME) : ccclass) class Cls extends Component {}
|
|
return Cls;
|
|
})();
|
|
} else {
|
|
Cls_ = (() => {
|
|
@(withExplicitName ? ccclass(EXPLICIT_NAME) : ccclass) class Cls {}
|
|
return Cls;
|
|
})();
|
|
}
|
|
|
|
if (withinRequiringFrame) {
|
|
requiringFrame.pop();
|
|
}
|
|
|
|
try {
|
|
expect(getClassName(Cls_)).toBe(expectedName);
|
|
expect(_getClassId(Cls_)).toStrictEqual(expectedId);
|
|
} finally {
|
|
unregisterClass(Cls_);
|
|
}
|
|
});
|
|
}); |