fix: 兼容 Chrome 90 前端运行环境
- 为管理端与用户中心补齐旧浏览器运行时 API 和回归测试 - 增加现代 CSS 与选择器降级,保持现有界面效果 - 固定 Chrome 90 构建目标并补充兼容依赖
This commit is contained in:
108
easyflow-ui-admin/app/src/polyfills.test.ts
Normal file
108
easyflow-ui-admin/app/src/polyfills.test.ts
Normal file
@@ -0,0 +1,108 @@
|
||||
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
||||
|
||||
import {
|
||||
installArrayAtPolyfill,
|
||||
installObjectHasOwnPolyfill,
|
||||
installPromiseWithResolversPolyfill,
|
||||
installStringAtPolyfill,
|
||||
installStructuredClonePolyfill,
|
||||
installUrlCanParsePolyfill,
|
||||
} from './polyfills';
|
||||
|
||||
const descriptors = new Map<
|
||||
string,
|
||||
[object, PropertyKey, PropertyDescriptor | undefined]
|
||||
>();
|
||||
|
||||
function remember(key: string, target: object, property: PropertyKey) {
|
||||
descriptors.set(key, [
|
||||
target,
|
||||
property,
|
||||
Object.getOwnPropertyDescriptor(target, property),
|
||||
]);
|
||||
}
|
||||
|
||||
function remove(target: object, property: PropertyKey) {
|
||||
Reflect.deleteProperty(target, property);
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
remember('arrayAt', Array.prototype, 'at');
|
||||
remember('stringAt', String.prototype, 'at');
|
||||
remember('hasOwn', Object, 'hasOwn');
|
||||
remember('withResolvers', Promise, 'withResolvers');
|
||||
remember('structuredClone', globalThis, 'structuredClone');
|
||||
remember('canParse', URL, 'canParse');
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
for (const [target, property, descriptor] of descriptors.values()) {
|
||||
if (descriptor) Object.defineProperty(target, property, descriptor);
|
||||
else remove(target, property);
|
||||
}
|
||||
descriptors.clear();
|
||||
});
|
||||
|
||||
describe('chrome 90 browser polyfills', () => {
|
||||
it('installs Array.prototype.at and String.prototype.at', () => {
|
||||
remove(Array.prototype, 'at');
|
||||
remove(String.prototype, 'at');
|
||||
|
||||
installArrayAtPolyfill();
|
||||
installStringAtPolyfill();
|
||||
|
||||
expect(['first', 'last'].at(-1)).toBe('last');
|
||||
expect('EasyFlow'.at(-1)).toBe('w');
|
||||
expect('EasyFlow'.at(99)).toBeUndefined();
|
||||
});
|
||||
|
||||
it('installs Object.hasOwn without accepting inherited properties', () => {
|
||||
remove(Object, 'hasOwn');
|
||||
installObjectHasOwnPolyfill();
|
||||
|
||||
const value = Object.create({ inherited: true }) as { own?: boolean };
|
||||
value.own = true;
|
||||
expect(Object.hasOwn(value, 'own')).toBe(true);
|
||||
expect(Object.hasOwn(value, 'inherited')).toBe(false);
|
||||
});
|
||||
|
||||
it('installs Promise.withResolvers and exposes working callbacks', async () => {
|
||||
remove(Promise, 'withResolvers');
|
||||
installPromiseWithResolversPolyfill();
|
||||
|
||||
// eslint-disable-next-line n/no-unsupported-features/es-syntax -- 测试目标就是验证该 API 的兼容实现。
|
||||
const { promise, resolve } = Promise.withResolvers<string>();
|
||||
resolve('ready');
|
||||
await expect(promise).resolves.toBe('ready');
|
||||
});
|
||||
|
||||
it('installs structuredClone with complex value and cycle support', () => {
|
||||
remove(globalThis, 'structuredClone');
|
||||
installStructuredClonePolyfill();
|
||||
|
||||
const source: {
|
||||
createdAt: Date;
|
||||
lookup: Map<string, number>;
|
||||
self?: unknown;
|
||||
} = {
|
||||
createdAt: new Date('2026-07-15T00:00:00.000Z'),
|
||||
lookup: new Map([['answer', 2026]]),
|
||||
};
|
||||
source.self = source;
|
||||
const clone = structuredClone(source);
|
||||
|
||||
expect(clone).not.toBe(source);
|
||||
expect(clone.self).toBe(clone);
|
||||
expect(clone.createdAt).toEqual(source.createdAt);
|
||||
expect(clone.lookup.get('answer')).toBe(2026);
|
||||
});
|
||||
|
||||
it('installs URL.canParse for absolute and base-relative URLs', () => {
|
||||
remove(URL, 'canParse');
|
||||
installUrlCanParsePolyfill();
|
||||
|
||||
expect(URL.canParse('https://easyflow.example/chat')).toBe(true);
|
||||
expect(URL.canParse('/chat', 'https://easyflow.example')).toBe(true);
|
||||
expect(URL.canParse('/chat')).toBe(false);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user