|
@@ -0,0 +1,82 @@
|
|
|
+import { beforeEach, describe, expect, it } from 'vitest';
|
|
|
+
|
|
|
+import { loadScript } from '../resources';
|
|
|
+
|
|
|
+const testJsPath =
|
|
|
+ 'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js';
|
|
|
+
|
|
|
+describe('loadScript', () => {
|
|
|
+ beforeEach(() => {
|
|
|
+ // 每个测试前清空 head,保证环境干净
|
|
|
+ document.head.innerHTML = '';
|
|
|
+ });
|
|
|
+
|
|
|
+ it('should resolve when the script loads successfully', async () => {
|
|
|
+ const promise = loadScript(testJsPath);
|
|
|
+
|
|
|
+ // 此时脚本元素已被创建并插入
|
|
|
+ const script = document.querySelector(
|
|
|
+ `script[src="${testJsPath}"]`,
|
|
|
+ ) as HTMLScriptElement;
|
|
|
+ expect(script).toBeTruthy();
|
|
|
+
|
|
|
+ // 模拟加载成功
|
|
|
+ script.dispatchEvent(new Event('load'));
|
|
|
+
|
|
|
+ // 等待 promise resolve
|
|
|
+ await expect(promise).resolves.toBeUndefined();
|
|
|
+ });
|
|
|
+
|
|
|
+ it('should not insert duplicate script and resolve immediately if already loaded', async () => {
|
|
|
+ // 先手动插入一个相同 src 的 script
|
|
|
+ const existing = document.createElement('script');
|
|
|
+ existing.src = 'bar.js';
|
|
|
+ document.head.append(existing);
|
|
|
+
|
|
|
+ // 再次调用
|
|
|
+ const promise = loadScript('bar.js');
|
|
|
+
|
|
|
+ // 立即 resolve
|
|
|
+ await expect(promise).resolves.toBeUndefined();
|
|
|
+
|
|
|
+ // head 中只保留一个
|
|
|
+ const scripts = document.head.querySelectorAll('script[src="bar.js"]');
|
|
|
+ expect(scripts).toHaveLength(1);
|
|
|
+ });
|
|
|
+
|
|
|
+ it('should reject when the script fails to load', async () => {
|
|
|
+ const promise = loadScript('error.js');
|
|
|
+
|
|
|
+ const script = document.querySelector(
|
|
|
+ 'script[src="error.js"]',
|
|
|
+ ) as HTMLScriptElement;
|
|
|
+ expect(script).toBeTruthy();
|
|
|
+
|
|
|
+ // 模拟加载失败
|
|
|
+ script.dispatchEvent(new Event('error'));
|
|
|
+
|
|
|
+ await expect(promise).rejects.toThrow('Failed to load script: error.js');
|
|
|
+ });
|
|
|
+
|
|
|
+ it('should handle multiple concurrent calls and only insert one script tag', async () => {
|
|
|
+ const p1 = loadScript(testJsPath);
|
|
|
+ const p2 = loadScript(testJsPath);
|
|
|
+
|
|
|
+ const script = document.querySelector(
|
|
|
+ `script[src="${testJsPath}"]`,
|
|
|
+ ) as HTMLScriptElement;
|
|
|
+ expect(script).toBeTruthy();
|
|
|
+
|
|
|
+ // 触发一次 load,两个 promise 都应该 resolve
|
|
|
+ script.dispatchEvent(new Event('load'));
|
|
|
+
|
|
|
+ await expect(p1).resolves.toBeUndefined();
|
|
|
+ await expect(p2).resolves.toBeUndefined();
|
|
|
+
|
|
|
+ // 只插入一次
|
|
|
+ const scripts = document.head.querySelectorAll(
|
|
|
+ `script[src="${testJsPath}"]`,
|
|
|
+ );
|
|
|
+ expect(scripts).toHaveLength(1);
|
|
|
+ });
|
|
|
+});
|