刘光辉
11 小时以前 0dfe84494048ce27ba8449831782128412d3eb13
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
import { beforeEach, describe, expect, it, vi } from 'vitest';
 
const mocks = vi.hoisted(() => {
  const app = { mount: vi.fn(), provide: vi.fn(), use: vi.fn() };
  app.use.mockReturnValue(app);
  app.provide.mockReturnValue(app);
  return { antd: {}, app, bridge: {}, createApp: vi.fn(() => app), createBridge: vi.fn(), createPinia: vi.fn(() => ({ pinia: true })) };
});
 
vi.mock('vue', async (importOriginal) => ({ ...(await importOriginal<typeof import('vue')>()), createApp: mocks.createApp }));
vi.mock('pinia', async (importOriginal) => ({ ...(await importOriginal<typeof import('pinia')>()), createPinia: mocks.createPinia }));
vi.mock('ant-design-vue', () => ({ default: mocks.antd }));
vi.mock('../src/onlyoffice/bridge', () => ({ createOnlyOfficeBridge: mocks.createBridge }));
 
describe('main', () => {
  const validPlugin = () => ({
    callCommand: vi.fn(),
    executeCommand: vi.fn(),
    executeMethod: vi.fn(),
    onThemeChangedBase: vi.fn(),
  });
 
  beforeEach(() => {
    vi.resetModules();
    vi.clearAllMocks();
    mocks.app.use.mockReturnValue(mocks.app);
    mocks.app.provide.mockReturnValue(mocks.app);
    delete window.Asc;
  });
 
  it('创建 bridge、安装依赖、注入后挂载', async () => {
    const asc = { plugin: validPlugin(), scope: {} };
    window.Asc = asc as never;
    mocks.createBridge.mockReturnValue(mocks.bridge);
 
    await import('../src/main');
    const { default: App } = await import('../src/App.vue');
 
    expect(mocks.createApp).toHaveBeenCalledWith(App);
    expect(mocks.createBridge).toHaveBeenCalledWith(asc);
    expect(mocks.app.use.mock.calls).toEqual([[{ pinia: true }], [mocks.antd]]);
    expect(mocks.app.provide).toHaveBeenCalledWith('onlyOfficeBridge', mocks.bridge);
    expect(mocks.app.mount).toHaveBeenCalledWith('#app');
  });
 
  it('Asc 缺失时注入 null 且仍然挂载', async () => {
    await import('../src/main');
 
    expect(mocks.createBridge).not.toHaveBeenCalled();
    expect(mocks.app.provide).toHaveBeenCalledWith('onlyOfficeBridge', null);
    expect(mocks.app.mount).toHaveBeenCalledWith('#app');
  });
 
  it('SDK 握手前 plugin 方法尚未挂载时仍创建 bridge', async () => {
    const asc = { plugin: { attachEvent: vi.fn() }, scope: {} };
    window.Asc = asc as never;
    mocks.createBridge.mockReturnValue(mocks.bridge);
 
    await import('../src/main');
 
    expect(mocks.createBridge).toHaveBeenCalledWith(asc);
    expect(mocks.app.provide).toHaveBeenCalledWith('onlyOfficeBridge', mocks.bridge);
    expect(mocks.app.mount).toHaveBeenCalledWith('#app');
  });
 
  it('没有 SDK bootstrap 特征的空 plugin 注入 null', async () => {
    window.Asc = { plugin: {}, scope: {} } as never;
 
    await import('../src/main');
 
    expect(mocks.createBridge).not.toHaveBeenCalled();
    expect(mocks.app.provide).toHaveBeenCalledWith('onlyOfficeBridge', null);
  });
 
  it.each(['callCommand', 'executeMethod', 'executeCommand', 'onThemeChangedBase'] as const)(
    'Asc.plugin.%s 已存在但不是函数时不得创建 bridge',
    async (method) => {
      const plugin: Record<string, unknown> = validPlugin();
      plugin[method] = 'invalid';
      window.Asc = { plugin, scope: {} } as never;
 
      await import('../src/main');
 
      expect(mocks.createBridge).not.toHaveBeenCalled();
      expect(mocks.app.provide).toHaveBeenCalledWith('onlyOfficeBridge', null);
      expect(mocks.app.mount).toHaveBeenCalledWith('#app');
    },
  );
});