aglinxinyuan commented on code in PR #5004:
URL: https://github.com/apache/texera/pull/5004#discussion_r3222492708


##########
frontend/src/app/workspace/component/code-editor-dialog/code-editor.component.spec.ts:
##########
@@ -24,40 +24,150 @@ import { WorkflowActionService } from 
"../../service/workflow-graph/model/workfl
 import { mockJavaUDFPredicate, mockPoint } from 
"../../service/workflow-graph/model/mock-workflow-data";
 import { OperatorMetadataService } from 
"../../service/operator-metadata/operator-metadata.service";
 import { StubOperatorMetadataService } from 
"../../service/operator-metadata/stub-operator-metadata.service";
+import { mockOperatorMetaData } from 
"../../service/operator-metadata/mock-operator-metadata.data";
 import { commonTestProviders } from "../../../common/testing/test-utils";
+import { OperatorPredicate } from "../../types/workflow-common.interface";
+import { OperatorSchema } from "../../types/operator-schema.interface";
+import { of } from "rxjs";
 
-describe("CodeEditorDialogComponent", () => {
-  let component: CodeEditorComponent;
-  let fixture: ComponentFixture<CodeEditorComponent>;
+// Operator types that the constructor's language-detection branch must map
+// to `python`. Anything else falls through to `java`. Local to this spec so
+// we don't perturb the shared mock-workflow-data fixtures.
+const PYTHON_OPERATOR_TYPES = ["PythonUDFV2", "PythonUDFSourceV2", 
"DualInputPortsPythonUDFV2"];

Review Comment:
   Fixed in 90678f98c9 — added an  group, augmented the stub metadata with 
synthetic R schemas, updated the section comment to spell out all three 
branches (r / python / java), and added the parametrized assertions for both R 
types.



##########
frontend/src/app/workspace/component/code-editor-dialog/code-editor.component.spec.ts:
##########
@@ -24,40 +24,150 @@ import { WorkflowActionService } from 
"../../service/workflow-graph/model/workfl
 import { mockJavaUDFPredicate, mockPoint } from 
"../../service/workflow-graph/model/mock-workflow-data";
 import { OperatorMetadataService } from 
"../../service/operator-metadata/operator-metadata.service";
 import { StubOperatorMetadataService } from 
"../../service/operator-metadata/stub-operator-metadata.service";
+import { mockOperatorMetaData } from 
"../../service/operator-metadata/mock-operator-metadata.data";
 import { commonTestProviders } from "../../../common/testing/test-utils";
+import { OperatorPredicate } from "../../types/workflow-common.interface";
+import { OperatorSchema } from "../../types/operator-schema.interface";
+import { of } from "rxjs";
 
-describe("CodeEditorDialogComponent", () => {
-  let component: CodeEditorComponent;
-  let fixture: ComponentFixture<CodeEditorComponent>;
+// Operator types that the constructor's language-detection branch must map
+// to `python`. Anything else falls through to `java`. Local to this spec so
+// we don't perturb the shared mock-workflow-data fixtures.
+const PYTHON_OPERATOR_TYPES = ["PythonUDFV2", "PythonUDFSourceV2", 
"DualInputPortsPythonUDFV2"];
+
+// Augment `mockOperatorMetaData` with synthetic schemas for the V2 operator
+// types and one unknown type so `addOperator` and `JointUIService` accept
+// them. Cloning the existing `PythonUDF` schema and renaming the
+// `operatorType` is the cheapest way to satisfy both `operatorTypeExists`
+// and the schema-driven joint element creation.
+const baseSchema = mockOperatorMetaData.operators.find(op => op.operatorType 
=== "PythonUDF");
+if (!baseSchema) {
+  throw new Error(
+    "CodeEditorComponent spec setup expected a PythonUDF schema in 
mockOperatorMetaData — fixture has drifted."
+  );
+}
+const synthesizeSchema = (operatorType: string): OperatorSchema => ({ 
...baseSchema, operatorType });
+const augmentedSchemas: OperatorSchema[] = [
+  ...mockOperatorMetaData.operators,
+  ...PYTHON_OPERATOR_TYPES.map(synthesizeSchema),
+  synthesizeSchema("SomeUnknownType"),
+];
+class AugmentedStubMetadataService extends StubOperatorMetadataService {
+  // JointUIService snapshots `operatorSchemas` from this stream once on
+  // construction, so we have to feed it the augmented list (overriding only
+  // `getOperatorSchema`/`operatorTypeExists` is not enough).
+  private readonly augmentedMetadata = of({
+    ...mockOperatorMetaData,
+    operators: augmentedSchemas,
+  });
+  override getOperatorMetadata(): typeof this.augmentedMetadata {
+    return this.augmentedMetadata;
+  }
+  override getOperatorSchema(operatorType: string): OperatorSchema {
+    const schema = augmentedSchemas.find(op => op.operatorType === 
operatorType);
+    if (!schema) throw new Error(`unknown operatorType ${operatorType}`);
+    return schema;
+  }
+  override operatorTypeExists(operatorType: string): boolean {
+    return augmentedSchemas.some(op => op.operatorType === operatorType);
+  }
+}
+
+const buildPredicate = (operatorID: string, operatorType: string): 
OperatorPredicate => ({
+  operatorID,
+  operatorType,
+  operatorVersion: "p1",
+  operatorProperties: {},
+  inputPorts: [{ portID: "input-0" }],
+  outputPorts: [{ portID: "output-0" }],
+  showAdvanced: false,
+  isDisabled: false,
+});
+
+describe("CodeEditorComponent", () => {
   let workflowActionService: WorkflowActionService;
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
       providers: [
         WorkflowActionService,
-        {
-          provide: OperatorMetadataService,
-          useClass: StubOperatorMetadataService,
-        },
+        { provide: OperatorMetadataService, useClass: 
AugmentedStubMetadataService },
         ...commonTestProviders,
       ],
       imports: [CodeEditorComponent, HttpClientTestingModule],
     }).compileComponents();
 
     workflowActionService = TestBed.inject(WorkflowActionService);
-    workflowActionService.addOperator(mockJavaUDFPredicate, mockPoint);
-    
workflowActionService.getJointGraphWrapper().highlightOperators(mockJavaUDFPredicate.operatorID);
-    fixture = TestBed.createComponent(CodeEditorComponent);
-    component = fixture.componentInstance;
+  });
+
+  function makeFixture(predicate: OperatorPredicate): 
ComponentFixture<CodeEditorComponent> {
+    workflowActionService.addOperator(predicate, mockPoint);
+    
workflowActionService.getJointGraphWrapper().highlightOperators(predicate.operatorID);
+    const fixture = TestBed.createComponent(CodeEditorComponent);
     fixture.detectChanges();
+    return fixture;
+  }
+
+  it("creates with the highlighted operator", () => {
+    const fixture = makeFixture(mockJavaUDFPredicate);
+    expect(fixture.componentInstance).toBeTruthy();
+    
expect(fixture.componentInstance.currentOperatorId).toBe(mockJavaUDFPredicate.operatorID);
   });
 
-  it("should create", () => {
-    expect(component).toBeTruthy();
+  // Language detection — the three V2-era operator types must always pick
+  // `python`, and any other type must pick `java`. The exact branch lives
+  // in the constructor; the public `language` field is what the rest of
+  // the editor (LSP wiring, file-suffix selection) keys off.
+
+  PYTHON_OPERATOR_TYPES.forEach((operatorType, index) => {
+    it(`picks language="python" for operatorType=${operatorType}`, () => {
+      const fixture = makeFixture(buildPredicate(`p-${index}`, operatorType));
+      expect(fixture.componentInstance.language).toBe("python");
+      expect(fixture.componentInstance.languageTitle).toBe("Python UDF");
+    });
   });
 
-  // it("should create a websocket when the editor is opened", () => {
-  //   let socketInstance = component.getLanguageServerSocket();
-  //   expect(socketInstance).toBeTruthy();
-  // });
+  it('picks language="java" for plain JavaUDF', () => {
+    const fixture = makeFixture(mockJavaUDFPredicate);
+    expect(fixture.componentInstance.language).toBe("java");
+    expect(fixture.componentInstance.languageTitle).toBe("Java UDF");
+  });
+
+  it('picks language="java" for unknown operator types', () => {
+    const fixture = makeFixture(buildPredicate("u-0", "SomeUnknownType"));
+    expect(fixture.componentInstance.language).toBe("java");
+    expect(fixture.componentInstance.languageTitle).toBe("Java UDF");
+  });
+
+  it("derives languageTitle as Capitalized(language) + ' UDF'", () => {
+    const fixture = makeFixture(buildPredicate("p-x", "PythonUDFV2"));
+    const c = fixture.componentInstance;
+    // Independent re-derivation matches whatever the component computed.
+    const expected = `${c.language[0].toUpperCase()}${c.language.slice(1)} 
UDF`;
+    expect(c.languageTitle).toBe(expected);
+  });
+
+  // Coeditor cursor styles — getCoeditorCursorStyles takes the awareness-
+  // sourced clientId + colour and returns a SafeStyle. We assert the wrapper
+  // shape (truthy DomSanitizer-wrapped object) for valid inputs. Exact CSS
+  // contents are sanitizer-internal and differ across builds, so we don't
+  // pin them here.
+
+  it("produces a SafeStyle for a coeditor with a numeric clientId and a hex 
colour", () => {
+    const fixture = makeFixture(mockJavaUDFPredicate);

Review Comment:
   Fixed in 90678f98c9 — renamed the comment block and both test descriptions 
from "SafeStyle" to "SafeHtml" to match the actual  return type.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to