Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
368d467
feat(ci): implement unit tests
rithvik-doshi Nov 25, 2025
e1d484f
ci: unit-tests
rithvik-doshi Nov 25, 2025
44c261d
Comment out GitHub Actions workflow steps
rithvik-doshi Nov 25, 2025
5df6a12
fix: improve the python test by calling the actual file
rithvik-doshi Nov 25, 2025
9be43a9
ci: test name
rithvik-doshi Dec 2, 2025
2104dc5
Merge branch 'default-app' into unit-test
rithvik-doshi Dec 2, 2025
05ffb24
Merge branch 'default-app' of github.com:SEMOSS/Template into unit-test
tevanburen Dec 2, 2025
40c07d5
ci: rework test and use specific snapshot version and update pom slig…
rithvik-doshi Dec 3, 2025
c16eb5b
fix: fix
rithvik-doshi Dec 3, 2025
80193cd
fix: fix
rithvik-doshi Dec 3, 2025
e04a3fa
chore: oopsy
rithvik-doshi Dec 3, 2025
ea67ee6
ci: fix pom
rithvik-doshi Dec 3, 2025
2248ed2
ci: fix script
rithvik-doshi Dec 3, 2025
8f040fc
ci: update commands
rithvik-doshi Dec 3, 2025
af02b47
ci: safe directory
rithvik-doshi Dec 3, 2025
942674d
fix: fix
rithvik-doshi Dec 3, 2025
dae6960
fix: oops
rithvik-doshi Dec 3, 2025
daf8239
fix: some weirdness and disabling push for now
rithvik-doshi Dec 3, 2025
128554c
fix: some weirdness and disabling push for now
rithvik-doshi Dec 3, 2025
b6d5af2
fix: fix
rithvik-doshi Dec 3, 2025
3fb274b
fix: fix
rithvik-doshi Dec 3, 2025
11a5f96
fix: fix
rithvik-doshi Dec 3, 2025
385a928
fix: fix
rithvik-doshi Dec 3, 2025
3cefc04
Merge branch 'default-app' into unit-test
rithvik-doshi Dec 3, 2025
e52736a
docs: docs and comment
rithvik-doshi Dec 3, 2025
e9cfca4
Merge branch 'unit-test' of https://github.com/SEMOSS/Template into u…
rithvik-doshi Dec 3, 2025
deeb89c
ci: report test
rithvik-doshi Dec 3, 2025
b3d4281
ci: report test
rithvik-doshi Dec 3, 2025
59c30a0
ci: we r done probably
rithvik-doshi Dec 3, 2025
ec5de8c
feat: routes
tevanburen Dec 3, 2025
69096e3
Merge branch 'default-app' into unit-test
rithvik-doshi Dec 3, 2025
cc4722d
Merge pull request #37 from SEMOSS/unit-test
rithvik-doshi Dec 3, 2025
81c57de
fix: some options
rithvik-doshi Dec 3, 2025
932a4e2
fix: skip if cache hit
rithvik-doshi Dec 3, 2025
690bff6
fix: workflow
rithvik-doshi Dec 3, 2025
118024e
fix: echos
rithvik-doshi Dec 3, 2025
27c8d7d
docs: comment
rithvik-doshi Dec 3, 2025
b0b4968
Revert "feat: routes"
tevanburen Dec 3, 2025
5ec1da6
Merge branch 'default-app' of github.com:SEMOSS/Template into kyle-merge
tevanburen Dec 3, 2025
bcbc2d8
feat: clean up
tevanburen Dec 3, 2025
9b7360d
fix: comments etc
tevanburen Dec 3, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/pre-commit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ name: Pre-commit
on:
pull_request:
branches: [ default-app ]
workflow_dispatch:

jobs:
pre-commit:
Expand Down
67 changes: 67 additions & 0 deletions .github/workflows/unit-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
name: Run Unit Tests

on:
pull_request:
branches: [ default-app ]
workflow_dispatch:
inputs:
snapshot:
description: 'CI version snapshot'
required: true
default: '5.0.0-alpha-SNAPSHOT'
type: choice
options:
- '5.0.0-alpha-SNAPSHOT'
# Add other snapshot versions as needed here!
use_cache:
description: 'Use cached Maven dependencies if available'
required: true
default: true
type: boolean
clean_install:
description: 'Run `mvn clean install -U` if not using cache'
required: true
default: false
type: boolean

jobs:
test:
name: Run Test Suite
runs-on: ubuntu-latest
container: maven:3.9.9-amazoncorretto-21-debian
env:
SNAPSHOT: ${{ inputs.snapshot || '5.0.0-alpha-SNAPSHOT' }}
USE_CACHE: ${{ inputs.use_cache || 'true' }}
CLEAN_INSTALL: ${{ inputs.clean_install || 'false' }}

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Cache Maven packages
id: cache-maven
if: env.USE_CACHE == 'true'
uses: actions/cache@v4
with:
path: /root/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: |
${{ runner.os }}-maven-

- name: Maven Install
if: env.USE_CACHE == 'false' || steps.cache-maven.outputs.cache-hit != 'true'
run: |
echo "Clean install: ${CLEAN_INSTALL}"
echo "Version snapshot: ${SNAPSHOT}"
if [ "${CLEAN_INSTALL}" = "true" ]; then
echo "Running mvn clean install with -U flag"
mvn clean install -U -DskipTests=true -Dci.version="${SNAPSHOT}" | grep -v "^Progress ([0-9]\+):"
else
echo "Running mvn install without -U flag"
mvn install -DskipTests=true -Dci.version="${SNAPSHOT}" | grep -v "^Progress ([0-9]\+):"
fi

- name: Run Unit Tests
run: |
mvn test -Dci.version="${SNAPSHOT}" | grep -v "^Progress ([0-9]\+):"

1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ client/node_modules/
portals/
classes/
target/
test-classes/

# Local configuration files
*.local
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ This repository includes several tools to help maintain code quality:

- See `client/README.md` for front-end development instructions.
- See `java/README.md` for back-end/reactor development.
- See `test/README.md` for comprehensive testing guide and workflow.

---

Expand Down
50 changes: 40 additions & 10 deletions client/src/components/base/DefaultToolView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
} from "@/components/ui/select";
import { Textarea } from "@/components/ui/textarea";
import { useAppContext } from "@/contexts";
import { PAGE_TYPES } from "@/pages";
import { PAGE_TYPES } from "@/routes.constants";
import type { MCPTool } from "@/types";
import { LoadingScreen } from "./LoadingScreen";

Expand All @@ -31,27 +31,49 @@ const getProcessedToolName = (toolName: string) => {
interface DefaultToolViewProps {
name: string;
}

/**
* Renders a default view for MCP tools based on their input schema. If a custom page is defined in PAGE_TYPES, it renders that instead
*
* @component
*/
export const DefaultToolView: React.FC<DefaultToolViewProps> = ({ name }) => {
const { actions } = useInsight();
const { tool, tools, isAppDataLoading } = useAppContext();
/**
* Library hooks
*/
const { actions, tool } = useInsight();
const { tools, isAppDataLoading } = useAppContext();

/**
* State
*/
const [selectedTool, setSelectedTool] = useState<MCPTool>(null);
const [formData, setFormData] = useState<Record<string, unknown>>(
tool?.parameters || {},
);
const [isSubmitting, setIsSubmitting] = useState(false);

/**
* Constants
*/
const properties = selectedTool?.inputSchema?.properties || {};
const required = selectedTool?.inputSchema?.required || [];
const toolName = tool?.name ? getProcessedToolName(tool?.name || "") : name;
const lowerName = toolName.toLocaleLowerCase();

/**
* Effects
*/
useEffect(() => {
// if (tools?.status === "SUCCESS") {
setSelectedTool(tools.find((a) => a.name === toolName));
// }
}, [tools, toolName]);

// biome-ignore lint/suspicious/noExplicitAny: Form data can be any type
const handleChange = (field: string, value: any) => {
/**
* Functions
*/
const handleChange = (field: string, value: unknown) => {
setFormData({ ...formData, [field]: value });
};

Expand All @@ -76,8 +98,17 @@ export const DefaultToolView: React.FC<DefaultToolViewProps> = ({ name }) => {
.join(" ");
};

// biome-ignore lint/suspicious/noExplicitAny: JSON Schema can be any structure
const renderField = (fieldName: string, fieldSchema: any) => {
const renderField = (
fieldName: string,
fieldSchema: {
type: string;
description?: string;
enum?: string[];
maxLength?: number;
minimum?: number;
maximum?: number;
},
) => {
const isRequired = required.includes(fieldName);
const value = formData[fieldName] ?? "";
const displayName = capitalizeWords(fieldName); // Capitalize fieldName
Expand Down Expand Up @@ -110,7 +141,7 @@ export const DefaultToolView: React.FC<DefaultToolViewProps> = ({ name }) => {
/>
</SelectTrigger>
<SelectContent>
{fieldSchema.enum.map((option: string) => (
{fieldSchema.enum.map((option) => (
<SelectItem key={option} value={option}>
{capitalizeWords(option)}
</SelectItem>
Expand Down Expand Up @@ -315,12 +346,11 @@ export const DefaultToolView: React.FC<DefaultToolViewProps> = ({ name }) => {
}
};

// Show loading screen if app data is loading or tool is not yet selected
if (isAppDataLoading || !selectedTool) {
return <LoadingScreen />;
}

const lowerName = toolName.toLocaleLowerCase();

// Render custom route if defined in route.constants.tsx else show default view
return Object.hasOwn(PAGE_TYPES, lowerName) ? (
PAGE_TYPES[lowerName]
Expand Down
2 changes: 1 addition & 1 deletion client/src/pages/Router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ import {
} from "react-router-dom";
import { DefaultToolView, LoadingScreen, PageWrapper } from "@/components";
import { useAppContext } from "@/contexts";
import { ROUTE_PATH_LOGIN_PAGE } from "@/routes.constants";
import { ErrorPage } from "./ErrorPage";
import { HomePage } from "./HomePage";
import { LoginPage } from "./LoginPage";
import { AuthorizedLayout, InitializedLayout } from "./layouts";
import { MCPLayout } from "./layouts/MCPLayout";
import { ROUTE_PATH_LOGIN_PAGE } from "./routes.constants";

const router = createHashRouter([
{
Expand Down
6 changes: 0 additions & 6 deletions client/src/pages/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1 @@
export * from "./Router";
export * from "./routes.constants";

// Re-export page components for external use
export { HomePage } from "./HomePage";
export { LoginPage } from "./LoginPage";
export { ErrorPage } from "./ErrorPage";
2 changes: 1 addition & 1 deletion client/src/pages/layouts/AuthorizedLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useInsight } from "@semoss/sdk/react";
import { Navigate, Outlet, useLocation } from "react-router-dom";
import { LoadingScreen } from "@/components";
import { useAppContext } from "@/contexts";
import { ROUTE_PATH_LOGIN_PAGE } from "../routes.constants";
import { ROUTE_PATH_LOGIN_PAGE } from "@/routes.constants";

/**
* Sends users to the login page if they are not authorized, shows a loading screen while app data is loading, otherwise renders the child components.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { GetStockHistory } from "../components/mcp/GetStockHistory";
import { GetStockPrice } from "../components/mcp/GetStockPrice";
import { GetStockHistory } from "./components/mcp/GetStockHistory";
import { GetStockPrice } from "./components/mcp/GetStockPrice";

export const ROUTE_PATH_LOGIN_PAGE = "login";

/**
Expand Down
55 changes: 54 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
</properties>
<build>
<sourceDirectory>java/src</sourceDirectory>
<testSourceDirectory>test</testSourceDirectory>
<outputDirectory>classes</outputDirectory>
<testOutputDirectory>test-classes</testOutputDirectory>
<resources>
<resource>
<directory>java</directory>
Expand Down Expand Up @@ -61,6 +63,26 @@
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>public</id>
<name>Sonatype's Maven repository</name>
<url>https://oss.sonatype.org/content/groups/public</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>sonatype-snapshots</id>
<name>Sonatype Snapshots</name>
<url>https://central.sonatype.com/repository/maven-snapshots</url>
<snapshots>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
</snapshots>
</repository>
<repository>
<id>3rdPartyJARs</id>
<name>Maven repository</name>
Expand All @@ -80,6 +102,38 @@
<version>${ci.version}</version>
<scope>provided</scope>
</dependency>
<!-- testing jars -->
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>6.0.0</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.junit.platform/junit-platform-suite -->
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-suite</artifactId>
<version>6.0.0</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mockito/mockito-core -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>5.18.0</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy</artifactId>
</exclusion>
<exclusion>
<groupId>org.objenesis</groupId>
<artifactId>objenesis</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<reporting>
<plugins>
Expand All @@ -89,7 +143,6 @@
<version>3.6.3</version>
<configuration>
<source>21</source>
<target>21</target>
<encoding>UTF-8</encoding>
<show>private</show>
<nohelp>true</nohelp>
Expand Down
Loading