* -------------------------------------------------------------------------
* This file is part of the MindStudio project.
* Copyright (c) 2026 Huawei Technologies Co.,Ltd.
*
* MindStudio is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
* -------------------------------------------------------------------------
*/
import { safeStringify } from './safeStringify';
describe('safeStringify - 黑盒行为验证', () => {
test('访问触发 ownKeys 异常的 Proxy 应返回 [Unserializable]', () => {
const handler: ProxyHandler<Record<string, never>> = {
ownKeys() {
throw new Error('Blocked by ownKeys trap');
}
};
const unsafe = new Proxy({}, handler);
const result = safeStringify({ risky: unsafe });
const parsed = JSON.parse(result);
expect(parsed.risky).toBe('[Unserializable]');
const errorSpy = jest.spyOn(console, 'error');
safeStringify({ test: unsafe });
expect(errorSpy).not.toHaveBeenCalled();
errorSpy.mockRestore();
});
test('危险属性名应替换为 [Filtered]', () => {
const input = { safe: 'keep', window: {}, _context: null };
const parsed = JSON.parse(safeStringify(input));
expect(parsed.window).toBe('[Filtered]');
expect(parsed._context).toBe('[Filtered]');
expect(parsed.safe).toBe('keep');
});
test('含自身 __proto__ 属性的对象应标记为 [Complex Object]', () => {
const obj = Object.defineProperty({}, '__proto__', {
value: 'fake proto property',
enumerable: true,
configurable: true
});
const parsed = JSON.parse(safeStringify({ data: obj }));
expect(parsed.data).toBe('[Complex Object]');
});
test('循环引用应触发外层 catch,返回字符串 [Serialization Failed]', () => {
const circular: any = { name: 'loop' };
circular.self = circular;
const result = safeStringify(circular);
expect(result).toBe('[Serialization Failed]');
const errorSpy = jest.spyOn(console, 'error').mockImplementation();
safeStringify(circular);
expect(errorSpy).toHaveBeenCalledWith(
'Safe stringify failed:',
expect.any(TypeError)
);
errorSpy.mockRestore();
});
test('数组元素应正确替换且长度不变', () => {
const input = [
1,
{ $$typeof: Symbol.for('react.element') },
'safe',
{ tag: 1, key: 'x', stateNode: {} }
];
const result = JSON.parse(safeStringify(input));
expect(result).toEqual([1, '[React Element]', 'safe', '[React Fiber Node]']);
expect(result.length).toBe(4);
});
test('普通数据应完整保留', () => {
const input = { str: 'ok', num: 42, arr: [1, null, true] };
const parsed = JSON.parse(safeStringify(input));
expect(parsed).toEqual(input);
});
});