This is an automated email from the ASF dual-hosted git repository.
voidmatcha pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/zeppelin.git
The following commit(s) were added to refs/heads/master by this push:
new d7f24c1801 [ZEPPELIN-6703] Fix Angular shell test typecheck errors
d7f24c1801 is described below
commit d7f24c1801c644f4a2d39a2440393ecc630ebb08
Author: Minho Jang <[email protected]>
AuthorDate: Thu Nov 12 00:12:23 2026 +0900
[ZEPPELIN-6703] Fix Angular shell test typecheck errors
### What is this PR for?
Fix TypeScript errors across 10 files in the Angular shell test compilation.
This PR:
- Includes declarations for Vite raw imports and DOM iteration.
- Corrects test fixtures and lifecycle state assertions to match existing
contracts.
- Adds test-only declarations for G2 APIs missing from its bundled types.
### What type of PR is it?
Bug Fix
### What is the Jira issue?
* https://issues.apache.org/jira/browse/ZEPPELIN-6703
### How should this be tested?
From `zeppelin-web-angular`, build the internal libraries and check the
shell test compilation:
```bash
npm run build:projects
npx tsc -p src/tsconfig.spec.json --noEmit
```
Run the existing shell unit tests to check for regressions:
```bash
npm run test:shell
```
### Questions:
* Does the license files need to update? No.
* Is there breaking changes for older versions? No.
* Does this needs documentation? No.
Closes #5611 from miinhho/ZEPPELIN-6703-shell-monaco-types.
Signed-off-by: YONGJAE LEE <[email protected]>
---
zeppelin-web-angular/eslint.config.js | 1 +
.../app/core/paragraph-base/paragraph-base.spec.ts | 2 +-
.../core-read/notebook-core-read-host.spec.ts | 10 ++---
.../notebook-core-read.component.testbed.spec.ts | 5 ++-
.../workspace/notebook/notebook.component.spec.ts | 30 ++++++++++----
.../scatter-chart-visualization.component.spec.ts | 46 ++++++++++++++++------
zeppelin-web-angular/src/tsconfig.spec.json | 5 ++-
.../test/g2-dependency-compatibility.spec.ts | 2 +-
zeppelin-web-angular/test/g2-test-types.d.ts | 36 +++++++++++++++++
9 files changed, 109 insertions(+), 28 deletions(-)
diff --git a/zeppelin-web-angular/eslint.config.js
b/zeppelin-web-angular/eslint.config.js
index 7b7c9d5bde..8ad647b990 100644
--- a/zeppelin-web-angular/eslint.config.js
+++ b/zeppelin-web-angular/eslint.config.js
@@ -189,6 +189,7 @@ module.exports = tseslint.config(
'src/**/*.spec.ts',
'projects/zeppelin-{notebook-core,sdk,visualization}/**/*.spec.ts',
'test/**/*.spec.ts',
+ 'test/**/*.d.ts',
'test/test-setup.ts',
'test/notebook-core/**/*.ts',
'vitest.notebook-core.config.mts',
diff --git
a/zeppelin-web-angular/src/app/core/paragraph-base/paragraph-base.spec.ts
b/zeppelin-web-angular/src/app/core/paragraph-base/paragraph-base.spec.ts
index 201085ae0a..9f0c179f19 100644
--- a/zeppelin-web-angular/src/app/core/paragraph-base/paragraph-base.spec.ts
+++ b/zeppelin-web-angular/src/app/core/paragraph-base/paragraph-base.spec.ts
@@ -92,7 +92,7 @@ describe('ParagraphBase streaming state isolation', () => {
component.ngOnDestroy();
});
- it.each(['FINISHED', 'ERROR', 'ABORT', 'RUNNING', 'PENDING'])(
+ it.each(['FINISHED', 'ERROR', 'ABORT', 'RUNNING', 'PENDING'] as const)(
'keeps accumulating output when another paragraph becomes %s',
status => {
const component = new TestParagraph(paragraph('A'));
diff --git
a/zeppelin-web-angular/src/app/pages/workspace/notebook/core-read/notebook-core-read-host.spec.ts
b/zeppelin-web-angular/src/app/pages/workspace/notebook/core-read/notebook-core-read-host.spec.ts
index 8ed06cb0a1..83cf363d27 100644
---
a/zeppelin-web-angular/src/app/pages/workspace/notebook/core-read/notebook-core-read-host.spec.ts
+++
b/zeppelin-web-angular/src/app/pages/workspace/notebook/core-read/notebook-core-read-host.spec.ts
@@ -113,18 +113,18 @@ describe('NotebookCoreReadHost', () => {
expect(states[states.length - 1]).toMatchObject({ connected: true,
snapshot: { status: 'loading' } });
replyNote('A');
- expect(host.port.getSnapshot().status).toBe('ready');
+ expect(states[states.length - 1].snapshot.status).toBe('ready');
expect(new Set(states.map(({ snapshot }) =>
snapshot)).size).toBe(states.length);
});
it('ignores a reply that arrives after the connection dropped', () => {
- const { host, received, connectedStatus$, sent } = setup();
+ const { host, received, connectedStatus$, sent, states } = setup();
host.open({ kind: 'note', noteId: 'A' });
connectedStatus$.next(false);
received.next({ op: OP.NOTE, data: { note: note('A') }, msgId:
`msg-${sent.length}` } as Envelope);
- expect(host.port.getSnapshot().status).toBe('failed');
+ expect(states[states.length - 1].snapshot.status).toBe('failed');
});
it('reads the current target again on retry', () => {
@@ -137,7 +137,7 @@ describe('NotebookCoreReadHost', () => {
});
it('tears down exactly once and ignores everything afterwards', () => {
- const { host, received, connectedStatus$, sent, replyNote, completions } =
setup();
+ const { host, received, connectedStatus$, sent, replyNote, states,
completions } = setup();
host.open({ kind: 'note', noteId: 'A' });
host.dispose();
@@ -148,7 +148,7 @@ describe('NotebookCoreReadHost', () => {
connectedStatus$.next(false);
connectedStatus$.next(true);
- expect(host.port.getSnapshot().status).toBe('disposed');
+ expect(states[states.length - 1].snapshot.status).toBe('disposed');
expect(completions()).toBe(1);
expect(sent).toEqual(['GET_NOTE A']);
expect(received.observed).toBe(false);
diff --git
a/zeppelin-web-angular/src/app/pages/workspace/notebook/core-read/notebook-core-read.component.testbed.spec.ts
b/zeppelin-web-angular/src/app/pages/workspace/notebook/core-read/notebook-core-read.component.testbed.spec.ts
index 780d3afc37..ec114871d3 100644
---
a/zeppelin-web-angular/src/app/pages/workspace/notebook/core-read/notebook-core-read.component.testbed.spec.ts
+++
b/zeppelin-web-angular/src/app/pages/workspace/notebook/core-read/notebook-core-read.component.testbed.spec.ts
@@ -26,6 +26,7 @@ import { TicketService } from
'@zeppelin/services/ticket.service';
import { NotebookCoreReadComponent } from './notebook-core-read.component';
import template from './notebook-core-read.component.html?raw';
+import { NotebookCoreReadState } from './notebook-core-read-host';
@Component({
selector: 'zeppelin-notebook-paragraph-result',
@@ -142,6 +143,8 @@ describe('NotebookCoreReadComponent', () => {
reply(noteMessage('A', lastMsgId()));
const { host } = fixture.componentInstance;
const dispose = vi.spyOn(host, 'dispose');
+ const states: NotebookCoreReadState[] = [];
+ host.state$.subscribe(state => states.push(state));
const sentBefore = sent.length;
fixture.destroy();
@@ -149,7 +152,7 @@ describe('NotebookCoreReadComponent', () => {
messageService.connectedStatus$.next(true);
expect(dispose).toHaveBeenCalledTimes(1);
- expect(host.port.getSnapshot().status).toBe('disposed');
+ expect(states[states.length - 1].snapshot.status).toBe('disposed');
expect(sent).toHaveLength(sentBefore);
});
});
diff --git
a/zeppelin-web-angular/src/app/pages/workspace/notebook/notebook.component.spec.ts
b/zeppelin-web-angular/src/app/pages/workspace/notebook/notebook.component.spec.ts
index 1d8f07926f..f646ac5cea 100644
---
a/zeppelin-web-angular/src/app/pages/workspace/notebook/notebook.component.spec.ts
+++
b/zeppelin-web-angular/src/app/pages/workspace/notebook/notebook.component.spec.ts
@@ -87,12 +87,12 @@ describe('NotebookComponent', () => {
it('ignores stale interpreter bindings replies', () => {
const { component } = createComponent();
- const originalBindings = [{ id: 'existing', selected: true }];
- component.interpreterBindings = originalBindings as typeof
component.interpreterBindings;
+ const originalBindings = [{ id: 'existing', name: 'Existing', selected:
true, interpreters: [] }];
+ component.interpreterBindings = originalBindings;
const data: MessageReceiveDataTypeMap[OP.INTERPRETER_BINDINGS] = {
noteId: 'note-a',
- interpreterBindings: [{ id: 'stale', selected: false }]
+ interpreterBindings: [{ id: 'stale', name: 'Stale', selected: false,
interpreters: [] }]
};
component.loadInterpreterBindings(data);
@@ -136,12 +136,14 @@ describe('NotebookComponent', () => {
const data: MessageReceiveDataTypeMap[OP.INTERPRETER_BINDINGS] = {
noteId: 'note-b',
- interpreterBindings: [{ id: 'current', selected: true }]
+ interpreterBindings: [{ id: 'current', name: 'Current', selected: true,
interpreters: [] }]
};
component.loadInterpreterBindings(data);
- expect(component.interpreterBindings).toEqual([{ id: 'current', selected:
true }]);
+ expect(component.interpreterBindings).toEqual([
+ { id: 'current', name: 'Current', selected: true, interpreters: [] }
+ ]);
});
it('applies revision history for the active note', () => {
@@ -179,8 +181,22 @@ describe('NotebookComponent', () => {
const { component, messageService } = createComponent();
component.note = {
- paragraphs: []
- } as typeof component.note;
+ id: 'note-b',
+ name: 'Notebook',
+ path: '/Notebook',
+ defaultInterpreterGroup: 'spark',
+ paragraphs: [],
+ noteParams: {},
+ noteForms: {},
+ angularObjects: {},
+ config: {
+ releaseresource: false,
+ isZeppelinNotebookCronEnable: false,
+ looknfeel: 'default',
+ personalizedMode: 'false'
+ },
+ info: {}
+ };
const message: WebSocketMessage<MessageReceiveDataTypeMap,
OP.PARAGRAPH_ADDED> = {
op: OP.PARAGRAPH_ADDED,
diff --git
a/zeppelin-web-angular/src/app/visualizations/scatter-chart/scatter-chart-visualization.component.spec.ts
b/zeppelin-web-angular/src/app/visualizations/scatter-chart/scatter-chart-visualization.component.spec.ts
index a0cda74b8d..f870c9d742 100644
---
a/zeppelin-web-angular/src/app/visualizations/scatter-chart/scatter-chart-visualization.component.spec.ts
+++
b/zeppelin-web-angular/src/app/visualizations/scatter-chart/scatter-chart-visualization.component.spec.ts
@@ -73,19 +73,43 @@ const createChart = (): ScatterFixture => {
const chart = new G2.Chart({ container, width: 600, height: 400, renderer:
'svg', animate: false });
component.chart = chart;
- const points = (): MappedPoint[] =>
- chart
- .get('geoms')[0]
- .get('dataArray')
+ const points = (): MappedPoint[] => {
+ const dataArray = chart.get('geoms')[0].get('dataArray');
+ if (!dataArray) {
+ throw new Error('Expected rendered scatter data');
+ }
+ return dataArray
.flat()
+ .map(point => {
+ const { x, y, color, size } = point;
+ if (
+ typeof x !== 'number' ||
+ typeof y !== 'number' ||
+ typeof color !== 'string' ||
+ (size !== undefined && typeof size !== 'number')
+ ) {
+ throw new Error('Expected a mapped scatter point with scalar
positions, color and optional size');
+ }
+ return { x, y, color, size };
+ })
.sort((a: MappedPoint, b: MappedPoint) => a.x - b.x);
- const radii = (): number[] =>
- chart
- .get('geoms')[0]
- .get('shapeContainer')
+ };
+ const radii = (): number[] => {
+ const shapeContainer = chart.get('geoms')[0].get('shapeContainer');
+ if (!shapeContainer) {
+ throw new Error('Expected a rendered scatter shape container');
+ }
+ return shapeContainer
.get('children')
- .map((shape: { attr: (name: string) => number }) => shape.attr('radius'))
+ .map(shape => {
+ const radius = shape.attr('radius');
+ if (typeof radius !== 'number') {
+ throw new Error('Expected a rendered scatter marker with a numeric
radius');
+ }
+ return radius;
+ })
.sort((a: number, b: number) => a - b);
+ };
const selectSize = (name?: string) => {
config.setting.scatterChart!.size = name ? field(name,
table.columns.indexOf(name)) : undefined;
@@ -144,9 +168,7 @@ describe('ScatterChartVisualizationComponent point sizes',
() => {
.map((item: { name: string; value: string }) => ({ name:
item.name, value: item.value }))
);
const legendItems = () => {
- const legends: Record<string, Array<{ get: (name: string) => unknown }>>
= fixture.chart.get(
- 'legendController'
- ).legends;
+ const legends = fixture.chart.get('legendController').legends;
return Object.values(legends)
.flat()
.map(legend => legend.get('items'));
diff --git a/zeppelin-web-angular/src/tsconfig.spec.json
b/zeppelin-web-angular/src/tsconfig.spec.json
index 07cf05eef6..60953fc6d0 100644
--- a/zeppelin-web-angular/src/tsconfig.spec.json
+++ b/zeppelin-web-angular/src/tsconfig.spec.json
@@ -2,14 +2,17 @@
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../out-tsc/spec",
- "types": ["mathjax", "node"]
+ "types": ["mathjax", "node"],
+ "lib": ["es2018", "dom", "dom.iterable"]
},
+ "files": ["../node_modules/vite/client.d.ts"],
"include": [
"**/*.spec.ts",
"../projects/zeppelin-notebook-core/**/*.spec.ts",
"../projects/zeppelin-sdk/**/*.spec.ts",
"../projects/zeppelin-visualization/**/*.spec.ts",
"../test/**/*.spec.ts",
+ "../test/**/*.d.ts",
"../test/test-setup.ts",
"../vitest.notebook-core.config.mts",
"../vitest.shell.config.mts"
diff --git a/zeppelin-web-angular/test/g2-dependency-compatibility.spec.ts
b/zeppelin-web-angular/test/g2-dependency-compatibility.spec.ts
index 370ed1af96..1f98593c18 100644
--- a/zeppelin-web-angular/test/g2-dependency-compatibility.spec.ts
+++ b/zeppelin-web-angular/test/g2-dependency-compatibility.spec.ts
@@ -28,7 +28,7 @@ describe('G2 dependency compatibility', () => {
chart.interval().position('category*value').color('category');
chart.render();
expect(container.querySelector('svg')).not.toBeNull();
-
expect(chart.get('geoms')[0].get('shapeContainer').get('children')).toHaveLength(2);
+
expect(chart.get('geoms')[0].get('shapeContainer')?.get('children')).toHaveLength(2);
} finally {
chart.destroy();
container.remove();
diff --git a/zeppelin-web-angular/test/g2-test-types.d.ts
b/zeppelin-web-angular/test/g2-test-types.d.ts
new file mode 100644
index 0000000000..e3190cf9af
--- /dev/null
+++ b/zeppelin-web-angular/test/g2-test-types.d.ts
@@ -0,0 +1,36 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import type { TooltipItem } from '@antv/g2';
+
+// G2 3.5.x ships declarations validated against 3.0.4. These runtime APIs
+// are used by the shell tests but are absent from those declarations.
+declare module '@antv/g2' {
+ interface ChartProps {
+ renderer: 'canvas' | 'svg';
+ }
+
+ interface Chart {
+ get(name: 'geoms'): Geom[];
+ get(name: 'legendController'): {
+ legends: Record<string, Array<{ get(name: 'items'): unknown }>>;
+ };
+ getTooltipItems(point: { x: number; y: number }): Array<Pick<TooltipItem,
'name' | 'value'>>;
+ }
+
+ interface Geom {
+ get(name: 'dataArray'): Array<Array<Record<string, unknown>>> | undefined;
+ get(name: 'shapeContainer'): {
+ get(name: 'children'): Array<{ attr(name: 'radius'): unknown }>;
+ } | null;
+ }
+}