@lvce-editor/test-worker 14.8.0 → 14.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/api.d.ts CHANGED
@@ -86,6 +86,12 @@ export interface DroppedFileHandle {
86
86
  readonly id: number;
87
87
  }
88
88
 
89
+ export interface MockErrorResponse {
90
+ readonly code: string;
91
+ readonly error: string;
92
+ readonly statusCode: number;
93
+ }
94
+
89
95
  export interface MockResponseOptions {
90
96
  readonly text: string;
91
97
  }
@@ -128,6 +134,12 @@ export interface Dirent {
128
134
  readonly type: number;
129
135
  }
130
136
 
137
+ export interface LayoutExpectation extends LayoutExpectationObject {
138
+ readonly activeGroupIndex?: number;
139
+ readonly direction?: LayoutDirection;
140
+ readonly groups?: readonly LayoutExpectationObject[];
141
+ }
142
+
131
143
  export interface SelectItem2Options {
132
144
  readonly callbackCommand: string;
133
145
  readonly label: string;
@@ -137,6 +149,29 @@ export type ChatDebugInputName = "closeDetails" | "eventCategoryFilter" | "filte
137
149
 
138
150
  export type TokenRow = readonly string[];
139
151
 
152
+ export type LayoutDirection = "horizontal" | "vertical" | number;
153
+
154
+ export type LayoutExpectationValue = string | number | boolean | RegExp | null | readonly LayoutExpectationValue[] | LayoutExpectationObject;
155
+
156
+ export type LayoutExpectationObject = {
157
+ readonly [key: string]: LayoutExpectationValue | undefined;
158
+ };
159
+
160
+ export type LayoutGroupState = {
161
+ readonly id?: number | string;
162
+ readonly [key: string]: unknown;
163
+ };
164
+
165
+ export type LayoutState = {
166
+ readonly activeGroupId?: number | string;
167
+ readonly groups?: readonly LayoutGroupState[];
168
+ readonly [key: string]: unknown;
169
+ };
170
+
171
+ export type SavedState = {
172
+ readonly layout?: LayoutState;
173
+ };
174
+
140
175
  export type SearchInputType = "SearchValue" | "ReplaceValue" | "IncludeValue" | "ExcludeValue";
141
176
 
142
177
  interface Workspace {
@@ -210,6 +245,7 @@ interface Chat {
210
245
  readonly handleProjectListContextMenu: (id: number, x: number, y: number) => Promise<void>;
211
246
  readonly handleSubmit: () => Promise<void>;
212
247
  readonly mockBackendAuthResponse: (response: any) => Promise<void>;
248
+ readonly mockBackendSetHttpErrorResponse: (response: MockErrorResponse) => Promise<void>;
213
249
  readonly mockOpenAiResponse: (options: MockOpenAiResponseOptions) => Promise<void>;
214
250
  readonly mockOpenApiRequestGetAll: () => Promise<readonly any[]>;
215
251
  readonly mockOpenApiRequestReset: () => Promise<void>;
@@ -217,6 +253,7 @@ interface Chat {
217
253
  readonly mockOpenApiStreamPushChunk: (chunk: string) => Promise<void>;
218
254
  readonly mockOpenApiStreamReset: () => Promise<void>;
219
255
  readonly openAgentModePicker: () => Promise<void>;
256
+ readonly openDebugView: () => Promise<void>;
220
257
  readonly openGitBranchPicker: () => Promise<void>;
221
258
  readonly openMockSession: (sessionId: string, messages: readonly any[]) => Promise<void>;
222
259
  readonly openModelPicker: () => Promise<void>;
@@ -234,7 +271,10 @@ interface Chat {
234
271
  readonly setReasoningPickerEnabled: (enabled: boolean) => Promise<void>;
235
272
  readonly setScrollDownButtonEnabled: (enabled: boolean) => Promise<void>;
236
273
  readonly setSearchEnabled: (enabled: boolean) => Promise<void>;
274
+ readonly setShowChatListTime: (showTime: boolean) => Promise<any>;
237
275
  readonly setStreamingEnabled: (enabled: boolean) => Promise<void>;
276
+ readonly setUseOwnBackend: (enabled: boolean) => Promise<void>;
277
+ readonly shouldHaveComposerSelection: (start: number, end: number) => Promise<void>;
238
278
  readonly show: () => Promise<void>;
239
279
  readonly showComposerAttachmentPreviewOverlay: (attachmentId: string) => Promise<void>;
240
280
  readonly useMockApi: () => Promise<void>;
@@ -625,8 +665,9 @@ interface Main {
625
665
  readonly openUri: (uri: string) => Promise<void>;
626
666
  readonly save: () => Promise<void>;
627
667
  readonly saveAll: () => Promise<void>;
628
- readonly saveState: (uid: number) => Promise<any>;
668
+ readonly saveState: (uid: number) => Promise<SavedState>;
629
669
  readonly selectTab: (groupIndex: number, tabIndex: number) => Promise<void>;
670
+ readonly shouldHaveLayout: (expectedLayout: LayoutExpectation, uid?: number) => Promise<void>;
630
671
  readonly splitDown: () => Promise<void>;
631
672
  readonly splitRight: () => Promise<void>;
632
673
  }
@@ -1864,6 +1864,9 @@ const handleChatListContextMenu = async (eventX, eventY) => {
1864
1864
  const setBackendUrl = async url => {
1865
1865
  await invoke('Chat.setBackendUrl', url);
1866
1866
  };
1867
+ const setUseOwnBackend = async enabled => {
1868
+ await invoke('Chat.setUseOwnBackend', enabled);
1869
+ };
1867
1870
  const handleClickBack = async () => {
1868
1871
  await invoke('Chat.handleClickBack');
1869
1872
  };
@@ -1882,6 +1885,12 @@ const selectIndex$7 = async index => {
1882
1885
  const handleClickClose = async () => {
1883
1886
  await invoke('Chat.handleClickClose');
1884
1887
  };
1888
+ const shouldHaveComposerSelection = async (start, end) => {
1889
+ const selection = await invoke('Chat.getComposerSelection');
1890
+ if (selection.start !== start || selection.end !== end) {
1891
+ throw new Error(`Expected selection to be { start: ${start}, end: ${end} }, but got { start: ${selection.start}, end: ${selection.end} }`);
1892
+ }
1893
+ };
1885
1894
  const handleClickNew = async () => {
1886
1895
  await invoke('Chat.handleClickNew');
1887
1896
  };
@@ -1931,6 +1940,9 @@ const mockOpenApiStreamPushChunk = async chunk => {
1931
1940
  const openMockSession = async (sessionId, messages) => {
1932
1941
  await invoke('Chat.openMockSession', sessionId, messages);
1933
1942
  };
1943
+ const mockBackendSetHttpErrorResponse = async response => {
1944
+ await invoke('Chat.mockBackendSetHttpErrorResponse', response.statusCode, response);
1945
+ };
1934
1946
  const registerMockResponse = async options => {
1935
1947
  await invoke('Chat.registerMockResponse', options);
1936
1948
  };
@@ -2018,6 +2030,9 @@ const mockOpenAiResponse = async options => {
2018
2030
  const handleInputFocus = async () => {
2019
2031
  return execute$1('Chat.handleInputFocus', 'chat-list');
2020
2032
  };
2033
+ const openDebugView = async () => {
2034
+ return execute$1('Chat.openDebugViw');
2035
+ };
2021
2036
  const chatListFocusPrevious = async () => {
2022
2037
  return execute$1('Chat.chatListFocusPrevious');
2023
2038
  };
@@ -2036,6 +2051,9 @@ const setNowForTest = async now => {
2036
2051
  const getAuthState = async () => {
2037
2052
  return invoke('Chat.getAuthState');
2038
2053
  };
2054
+ const setShowChatListTime = async showTime => {
2055
+ return invoke('Chat.setShowChatListTime', showTime);
2056
+ };
2039
2057
  const handleAgentModeChange = async newAgentMode => {
2040
2058
  return invoke('Chat.handleAgentModeChange', newAgentMode);
2041
2059
  };
@@ -2075,6 +2093,7 @@ const Chat = {
2075
2093
  handleProjectListContextMenu,
2076
2094
  handleSubmit,
2077
2095
  mockBackendAuthResponse,
2096
+ mockBackendSetHttpErrorResponse,
2078
2097
  mockOpenAiResponse,
2079
2098
  mockOpenApiRequestGetAll,
2080
2099
  mockOpenApiRequestReset,
@@ -2082,6 +2101,7 @@ const Chat = {
2082
2101
  mockOpenApiStreamPushChunk,
2083
2102
  mockOpenApiStreamReset,
2084
2103
  openAgentModePicker,
2104
+ openDebugView,
2085
2105
  openGitBranchPicker,
2086
2106
  openMockSession,
2087
2107
  openModelPicker,
@@ -2099,7 +2119,10 @@ const Chat = {
2099
2119
  setReasoningPickerEnabled,
2100
2120
  setScrollDownButtonEnabled,
2101
2121
  setSearchEnabled,
2122
+ setShowChatListTime,
2102
2123
  setStreamingEnabled,
2124
+ setUseOwnBackend,
2125
+ shouldHaveComposerSelection,
2103
2126
  show: show$7,
2104
2127
  showComposerAttachmentPreviewOverlay,
2105
2128
  useMockApi
@@ -2333,12 +2356,92 @@ const Dialog = {
2333
2356
  showSaveFilePicker
2334
2357
  };
2335
2358
 
2359
+ const defaultMainAreaUid = 2;
2360
+ const directionMap = {
2361
+ horizontal: 1,
2362
+ vertical: 2
2363
+ };
2364
+ const isObject$1 = value => {
2365
+ return typeof value === 'object' && value !== null && !Array.isArray(value) && !(value instanceof RegExp);
2366
+ };
2367
+ const matchesExpectedArray = (actual, expected) => {
2368
+ if (!Array.isArray(actual) || actual.length !== expected.length) {
2369
+ return false;
2370
+ }
2371
+ for (let i = 0; i < expected.length; i++) {
2372
+ if (!matchesExpected(actual[i], expected[i])) {
2373
+ return false;
2374
+ }
2375
+ }
2376
+ return true;
2377
+ };
2378
+ const matchesExpectedObject = (actual, expected) => {
2379
+ if (!isObject$1(actual)) {
2380
+ return false;
2381
+ }
2382
+ for (const [childKey, childExpectedValue] of Object.entries(expected)) {
2383
+ if (childExpectedValue === undefined) {
2384
+ continue;
2385
+ }
2386
+ if (!matchesExpected(actual[childKey], childExpectedValue, childKey)) {
2387
+ return false;
2388
+ }
2389
+ }
2390
+ return true;
2391
+ };
2392
+ const matchesExpected = (actual, expected, key = '') => {
2393
+ if (key === 'direction' && typeof expected === 'string' && expected in directionMap) {
2394
+ return Object.is(actual, directionMap[expected]);
2395
+ }
2396
+ if (expected instanceof RegExp) {
2397
+ return typeof actual === 'string' && expected.test(actual);
2398
+ }
2399
+ if (Array.isArray(expected)) {
2400
+ return matchesExpectedArray(actual, expected);
2401
+ }
2402
+ if (isObject$1(expected)) {
2403
+ return matchesExpectedObject(actual, expected);
2404
+ }
2405
+ return Object.is(actual, expected);
2406
+ };
2407
+ const matchesActiveGroupIndex = (layout, activeGroupIndex) => {
2408
+ const groups = layout.groups || [];
2409
+ const group = groups[activeGroupIndex];
2410
+ if (!group) {
2411
+ return false;
2412
+ }
2413
+ return layout.activeGroupId === group.id;
2414
+ };
2415
+ const serializeForError = value => {
2416
+ return JSON.stringify(value, (_key, currentValue) => {
2417
+ if (currentValue instanceof RegExp) {
2418
+ return currentValue.toString();
2419
+ }
2420
+ return currentValue;
2421
+ });
2422
+ };
2336
2423
  const openUri = async uri => {
2337
2424
  await invoke('Main.openUri', uri);
2338
2425
  };
2339
2426
  const saveState = async uid => {
2340
2427
  return invoke('Main.saveState', uid);
2341
2428
  };
2429
+ const shouldHaveLayout = async (expectedLayout, uid = defaultMainAreaUid) => {
2430
+ const state = await saveState(uid);
2431
+ const actualLayout = state.layout;
2432
+ if (!actualLayout) {
2433
+ throw new AssertionError(`expected main layout to exist but state was ${serializeForError(state)}`);
2434
+ }
2435
+ const {
2436
+ activeGroupIndex,
2437
+ ...partialExpectedLayout
2438
+ } = expectedLayout;
2439
+ const matchesLayout = matchesExpected(actualLayout, partialExpectedLayout);
2440
+ const matchesActiveGroup = activeGroupIndex === undefined || matchesActiveGroupIndex(actualLayout, activeGroupIndex);
2441
+ if (!matchesLayout || !matchesActiveGroup) {
2442
+ throw new AssertionError(`expected main layout to match ${serializeForError(expectedLayout)} but was ${serializeForError(actualLayout)}`);
2443
+ }
2444
+ };
2342
2445
  const splitRight = async () => {
2343
2446
  await invoke('Main.splitRight');
2344
2447
  };
@@ -2429,6 +2532,7 @@ const Main = {
2429
2532
  saveAll,
2430
2533
  saveState,
2431
2534
  selectTab: selectTab$2,
2535
+ shouldHaveLayout,
2432
2536
  splitDown,
2433
2537
  splitRight
2434
2538
  };
@@ -4796,32 +4900,39 @@ const execute = async (href, platform, assetDir) => {
4796
4900
  // 1. get script to import from renderer process (url or from html)
4797
4901
  const scriptUrl = href;
4798
4902
  setUrl(scriptUrl); // TODO avoid side effect
4799
- // 2. import that script
4800
- const module = await importTest(scriptUrl);
4801
- const {
4802
- mockRpc,
4803
- name,
4804
- skip,
4805
- test
4806
- } = module;
4807
- if (mockRpc) {
4808
- setMockRpc(mockRpc);
4809
- }
4810
- if (test) {
4811
- if (skip) {
4812
- await skipTest(name);
4813
- } else {
4814
- await executeTest(name, test, globals);
4903
+ try {
4904
+ // 2. import that script
4905
+ const module = await importTest(scriptUrl);
4906
+ const {
4907
+ mockRpc,
4908
+ name,
4909
+ skip,
4910
+ test
4911
+ } = module;
4912
+ if (mockRpc) {
4913
+ setMockRpc(mockRpc);
4815
4914
  }
4915
+ if (test) {
4916
+ if (skip) {
4917
+ await skipTest(name);
4918
+ } else {
4919
+ await executeTest(name, test, globals);
4920
+ }
4921
+ }
4922
+ // TODO maybe setup file watcher earlier, to not miss events?
4923
+ } catch (error) {
4924
+ await printTestError(error);
4925
+ await invoke('TestFrameWork.showOverlay', Fail, 'red', `test failed: ${error}`);
4926
+ return;
4927
+ } finally {
4928
+ push({
4929
+ assetDir,
4930
+ inProgress: false,
4931
+ platform,
4932
+ url: href
4933
+ });
4816
4934
  }
4817
- // TODO maybe setup file watcher earlier, to not miss events?
4818
4935
 
4819
- push({
4820
- assetDir,
4821
- inProgress: false,
4822
- platform,
4823
- url: href
4824
- });
4825
4936
  // TODO if file watcher was previously added, don't need to add one
4826
4937
  try {
4827
4938
  if (await hotReloadEnabled()) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/test-worker",
3
- "version": "14.8.0",
3
+ "version": "14.10.0",
4
4
  "description": "Test Worker",
5
5
  "repository": {
6
6
  "type": "git",