From 0a1948a75814941ee022bd9cba3422a305f220db Mon Sep 17 00:00:00 2001 From: "Christian C. Berclaz" Date: Fri, 1 May 2026 23:04:03 +0200 Subject: [PATCH] test(scala): add integration test with multi-file fixture 3-file Scala fixture (User.scala, UserService.scala, Main.scala) exercising: file detection, class/trait/object extraction, method extraction, call edges, and cross-file resolution. --- .../lang-resolution/scala-app/Main.scala | 8 +++ .../scala-app/models/User.scala | 15 +++++ .../scala-app/services/UserService.scala | 14 ++++ .../test/integration/resolvers/scala.test.ts | 66 +++++++++++++++++++ 4 files changed, 103 insertions(+) create mode 100644 gitnexus/test/fixtures/lang-resolution/scala-app/Main.scala create mode 100644 gitnexus/test/fixtures/lang-resolution/scala-app/models/User.scala create mode 100644 gitnexus/test/fixtures/lang-resolution/scala-app/services/UserService.scala create mode 100644 gitnexus/test/integration/resolvers/scala.test.ts diff --git a/gitnexus/test/fixtures/lang-resolution/scala-app/Main.scala b/gitnexus/test/fixtures/lang-resolution/scala-app/Main.scala new file mode 100644 index 000000000..604683e95 --- /dev/null +++ b/gitnexus/test/fixtures/lang-resolution/scala-app/Main.scala @@ -0,0 +1,8 @@ +import services.UserService + +object Main { + def main(args: Array[String]): Unit = { + val user = UserService.createUser("Alice", "alice@example.com") + UserService.process(user) + } +} diff --git a/gitnexus/test/fixtures/lang-resolution/scala-app/models/User.scala b/gitnexus/test/fixtures/lang-resolution/scala-app/models/User.scala new file mode 100644 index 000000000..25c83fa38 --- /dev/null +++ b/gitnexus/test/fixtures/lang-resolution/scala-app/models/User.scala @@ -0,0 +1,15 @@ +package models + +trait Greeter { + def greet(name: String): String +} + +class User(val name: String, val email: String) extends Greeter { + def greet(name: String): String = s"Hello, $name" + + def getEmail: String = email +} + +object User { + def create(name: String, email: String): User = new User(name, email) +} diff --git a/gitnexus/test/fixtures/lang-resolution/scala-app/services/UserService.scala b/gitnexus/test/fixtures/lang-resolution/scala-app/services/UserService.scala new file mode 100644 index 000000000..56ba9be63 --- /dev/null +++ b/gitnexus/test/fixtures/lang-resolution/scala-app/services/UserService.scala @@ -0,0 +1,14 @@ +package services + +import models.User + +object UserService { + def createUser(name: String, email: String): User = { + User.create(name, email) + } + + def process(user: User): Unit = { + val greeting = user.greet(user.name) + println(greeting) + } +} diff --git a/gitnexus/test/integration/resolvers/scala.test.ts b/gitnexus/test/integration/resolvers/scala.test.ts new file mode 100644 index 000000000..be1dae82a --- /dev/null +++ b/gitnexus/test/integration/resolvers/scala.test.ts @@ -0,0 +1,66 @@ +/** + * Scala: basic pipeline integration — classes, traits, objects, methods, imports, calls. + * Verifies that the Scala language provider correctly parses JVM-style code + * with class/trait/object definitions, method extraction, and cross-file calls. + */ +import { describe, it, expect, beforeAll } from 'vitest'; +import path from 'path'; +import { + FIXTURES, + getRelationships, + getNodesByLabel, + runPipelineFromRepo, + type PipelineResult, +} from './helpers.js'; +import { isLanguageAvailable } from '../../../src/core/tree-sitter/parser-loader.js'; +import { SupportedLanguages } from '../../../src/config/supported-languages.js'; + +const scalaAvailable = isLanguageAvailable(SupportedLanguages.Scala); + +describe.skipIf(!scalaAvailable)('Scala pipeline integration', () => { + let result: PipelineResult; + + beforeAll(async () => { + result = await runPipelineFromRepo(path.join(FIXTURES, 'scala-app'), () => {}); + }, 60000); + + it('detects Scala files', () => { + const files = getNodesByLabel(result, 'File'); + expect(files).toContain('Main.scala'); + expect(files).toContain('User.scala'); + expect(files).toContain('UserService.scala'); + }); + + it('extracts classes, traits, and objects', () => { + const classes = getNodesByLabel(result, 'Class'); + const interfaces = getNodesByLabel(result, 'Interface'); + expect(classes).toContain('User'); + expect(classes).toContain('UserService'); + expect(classes).toContain('Main'); + expect(interfaces).toContain('Greeter'); + }); + + it('extracts methods', () => { + const methods = getNodesByLabel(result, 'Method'); + expect(methods).toContain('greet'); + expect(methods).toContain('getEmail'); + expect(methods).toContain('create'); + expect(methods).toContain('createUser'); + expect(methods).toContain('process'); + expect(methods).toContain('main'); + }); + + it('extracts call edges', () => { + const calls = getRelationships(result, 'CALLS'); + expect(calls.length).toBeGreaterThanOrEqual(1); + const callNames = calls.map((c) => c.target); + expect(callNames).toContain('create'); + }); + + it('extracts cross-file calls', () => { + const calls = getRelationships(result, 'CALLS'); + const callNames = calls.map((c) => c.target); + expect(callNames).toContain('createUser'); + expect(callNames).toContain('process'); + }); +});