Skip to content

Commit 69e0250

Browse files
chore: add frontend asset bundles and integration smoke test
- Rebuilt frontend assets (React SPA, Cytoscape, Monaco editor) - IntegrationSmokeTest for end-to-end pipeline validation Co-Authored-By: Paperclip <noreply@paperclip.ing>
1 parent 2d8f816 commit 69e0250

8 files changed

Lines changed: 1560 additions & 0 deletions

File tree

src/main/resources/static/assets/index-Bz09f9bO.js

Lines changed: 271 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/main/resources/static/assets/index-CRDi8AkO.js

Lines changed: 271 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/main/resources/static/assets/index-DAlDf3j_.js

Lines changed: 256 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/main/resources/static/assets/index-DSd8oUEX.css

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/main/resources/static/assets/vendor-cytoscape-Cs7n3zQ7.js

Lines changed: 331 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import"./vendor-react-D_IlqkXa.js";

src/main/resources/static/assets/vendor-react-D_IlqkXa.js

Lines changed: 192 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
1+
package io.github.randomcodespace.iq.e2e;
2+
3+
import io.github.randomcodespace.iq.analyzer.AnalysisResult;
4+
import io.github.randomcodespace.iq.analyzer.Analyzer;
5+
import io.github.randomcodespace.iq.analyzer.FileDiscovery;
6+
import io.github.randomcodespace.iq.analyzer.LayerClassifier;
7+
import io.github.randomcodespace.iq.analyzer.StructuredParser;
8+
import io.github.randomcodespace.iq.analyzer.linker.EntityLinker;
9+
import io.github.randomcodespace.iq.analyzer.linker.Linker;
10+
import io.github.randomcodespace.iq.analyzer.linker.ModuleContainmentLinker;
11+
import io.github.randomcodespace.iq.analyzer.linker.TopicLinker;
12+
import io.github.randomcodespace.iq.config.CodeIqConfig;
13+
import io.github.randomcodespace.iq.detector.Detector;
14+
import io.github.randomcodespace.iq.detector.DetectorRegistry;
15+
import io.github.randomcodespace.iq.model.CodeNode;
16+
import io.github.randomcodespace.iq.model.NodeKind;
17+
import org.junit.jupiter.api.Tag;
18+
import org.junit.jupiter.api.Test;
19+
import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;
20+
import org.springframework.beans.factory.config.BeanDefinition;
21+
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
22+
import org.springframework.core.type.filter.AssignableTypeFilter;
23+
24+
import java.nio.file.Files;
25+
import java.nio.file.Path;
26+
import java.util.ArrayList;
27+
import java.util.List;
28+
import java.util.Set;
29+
import java.util.stream.Collectors;
30+
31+
import static org.junit.jupiter.api.Assertions.*;
32+
33+
/**
34+
* Integration smoke tests that validate the analysis pipeline against
35+
* diverse real-world test repositories. Verifies no crashes, reasonable
36+
* node/edge counts, correct language detection, and basic sanity.
37+
*
38+
* <p>Enabled when {@code INTEGRATION_TEST_DIR} env var points to a directory
39+
* containing cloned test repos (terraform-vpc, kit, fastapi, kafka, nest, spring-boot).
40+
*
41+
* <pre>
42+
* INTEGRATION_TEST_DIR=/home/sandbox/projects/testDir \
43+
* mvn test -Dtest="IntegrationSmokeTest" -pl .
44+
* </pre>
45+
*/
46+
@Tag("integration")
47+
@EnabledIfEnvironmentVariable(named = "INTEGRATION_TEST_DIR", matches = ".+")
48+
class IntegrationSmokeTest {
49+
50+
private static Analyzer buildAnalyzer() {
51+
List<Detector> detectors = discoverDetectors();
52+
var registry = new DetectorRegistry(detectors);
53+
var parser = new StructuredParser();
54+
var config = new CodeIqConfig();
55+
var fileDiscovery = new FileDiscovery(config);
56+
var layerClassifier = new LayerClassifier();
57+
List<Linker> linkers = List.of(
58+
new EntityLinker(),
59+
new ModuleContainmentLinker(),
60+
new TopicLinker()
61+
);
62+
return new Analyzer(registry, parser, fileDiscovery, layerClassifier, linkers, config);
63+
}
64+
65+
@SuppressWarnings("unchecked")
66+
private static List<Detector> discoverDetectors() {
67+
var scanner = new ClassPathScanningCandidateComponentProvider(false);
68+
scanner.addIncludeFilter(new AssignableTypeFilter(Detector.class));
69+
List<Detector> detectors = new ArrayList<>();
70+
for (BeanDefinition bd : scanner.findCandidateComponents("io.github.randomcodespace.iq.detector")) {
71+
try {
72+
Class<? extends Detector> clazz = (Class<? extends Detector>) Class.forName(bd.getBeanClassName());
73+
if (!clazz.isInterface() && !java.lang.reflect.Modifier.isAbstract(clazz.getModifiers())) {
74+
detectors.add(clazz.getDeclaredConstructor().newInstance());
75+
}
76+
} catch (Exception e) {
77+
// Skip detectors that can't be instantiated
78+
}
79+
}
80+
return detectors;
81+
}
82+
83+
private Path repoDir(String name) {
84+
Path base = Path.of(System.getenv("INTEGRATION_TEST_DIR"));
85+
Path repo = base.resolve(name);
86+
assertTrue(Files.isDirectory(repo), "Test repo not found: " + repo);
87+
return repo;
88+
}
89+
90+
private AnalysisResult analyze(String repoName) {
91+
Analyzer analyzer = buildAnalyzer();
92+
return analyzer.run(repoDir(repoName), null);
93+
}
94+
95+
// --- Small: terraform-vpc (HCL) ---
96+
97+
@Test
98+
void terraformVpc_producesNodes() {
99+
AnalysisResult result = analyze("terraform-vpc");
100+
assertNotNull(result);
101+
assertTrue(result.nodeCount() >= 5,
102+
"terraform-vpc should produce at least 5 nodes, got " + result.nodeCount());
103+
104+
// Should detect node kinds
105+
assertNotNull(result.nodes());
106+
Set<NodeKind> kinds = result.nodes().stream()
107+
.map(CodeNode::getKind)
108+
.collect(Collectors.toSet());
109+
assertFalse(kinds.isEmpty(), "Should detect multiple node kinds");
110+
}
111+
112+
// --- Medium: kit (Go) ---
113+
114+
@Test
115+
void kit_producesGoNodes() {
116+
AnalysisResult result = analyze("kit");
117+
assertNotNull(result);
118+
assertTrue(result.nodeCount() >= 50,
119+
"kit (Go) should produce at least 50 nodes, got " + result.nodeCount());
120+
121+
// Should detect Go via language breakdown
122+
assertNotNull(result.languageBreakdown());
123+
assertTrue(result.languageBreakdown().containsKey("go"),
124+
"kit should detect Go language, found: " + result.languageBreakdown().keySet());
125+
}
126+
127+
// --- Medium: fastapi (Python) ---
128+
129+
@Test
130+
void fastapi_producesPythonNodes() {
131+
AnalysisResult result = analyze("fastapi");
132+
assertNotNull(result);
133+
assertTrue(result.nodeCount() >= 100,
134+
"fastapi should produce at least 100 nodes, got " + result.nodeCount());
135+
136+
assertNotNull(result.languageBreakdown());
137+
assertTrue(result.languageBreakdown().containsKey("python"),
138+
"fastapi should detect Python, found: " + result.languageBreakdown().keySet());
139+
}
140+
141+
// --- Large: kafka (Java/Scala) ---
142+
143+
@Test
144+
void kafka_producesJavaNodes() {
145+
AnalysisResult result = analyze("kafka");
146+
assertNotNull(result);
147+
assertTrue(result.nodeCount() >= 500,
148+
"kafka should produce at least 500 nodes, got " + result.nodeCount());
149+
150+
assertNotNull(result.languageBreakdown());
151+
boolean hasJavaOrScala = result.languageBreakdown().containsKey("java")
152+
|| result.languageBreakdown().containsKey("scala");
153+
assertTrue(hasJavaOrScala,
154+
"kafka should detect Java or Scala, found: " + result.languageBreakdown().keySet());
155+
}
156+
157+
// --- Large: nest (TypeScript) ---
158+
159+
@Test
160+
void nest_producesTypeScriptNodes() {
161+
AnalysisResult result = analyze("nest");
162+
assertNotNull(result);
163+
assertTrue(result.nodeCount() >= 200,
164+
"nest should produce at least 200 nodes, got " + result.nodeCount());
165+
166+
assertNotNull(result.languageBreakdown());
167+
assertTrue(result.languageBreakdown().containsKey("typescript"),
168+
"nest should detect TypeScript, found: " + result.languageBreakdown().keySet());
169+
}
170+
171+
// --- Monorepo: spring-boot (Java) ---
172+
173+
@Test
174+
void springBoot_producesLargeGraph() {
175+
AnalysisResult result = analyze("spring-boot");
176+
assertNotNull(result);
177+
assertTrue(result.nodeCount() >= 1000,
178+
"spring-boot monorepo should produce at least 1000 nodes, got " + result.nodeCount());
179+
180+
// Should have edges
181+
assertTrue(result.edgeCount() > 0,
182+
"spring-boot should produce edges");
183+
184+
// Should detect Java
185+
assertNotNull(result.languageBreakdown());
186+
assertTrue(result.languageBreakdown().containsKey("java"),
187+
"spring-boot should detect Java, found: " + result.languageBreakdown().keySet());
188+
}
189+
190+
// --- Cross-cutting: edge sanity ---
191+
192+
@Test
193+
void smallRepos_edgesReferenceValidNodes() {
194+
for (String repo : List.of("terraform-vpc", "kit")) {
195+
AnalysisResult result = analyze(repo);
196+
assertNotNull(result.nodes(), repo + " should return nodes list");
197+
198+
Set<String> nodeIds = result.nodes().stream()
199+
.map(CodeNode::getId)
200+
.collect(Collectors.toSet());
201+
202+
// Verify edges on nodes reference valid targets
203+
for (CodeNode node : result.nodes()) {
204+
for (var edge : node.getEdges()) {
205+
assertTrue(nodeIds.contains(edge.getSourceId()),
206+
repo + ": Edge source " + edge.getSourceId() + " not found in nodes");
207+
if (edge.getTarget() != null) {
208+
assertTrue(nodeIds.contains(edge.getTarget().getId()),
209+
repo + ": Edge target " + edge.getTarget().getId() + " not found in nodes");
210+
}
211+
}
212+
}
213+
}
214+
}
215+
216+
// --- Determinism ---
217+
218+
@Test
219+
void terraformVpc_deterministicOutput() {
220+
AnalysisResult first = analyze("terraform-vpc");
221+
AnalysisResult second = analyze("terraform-vpc");
222+
223+
assertEquals(first.nodeCount(), second.nodeCount(),
224+
"Node count should be deterministic");
225+
assertEquals(first.edgeCount(), second.edgeCount(),
226+
"Edge count should be deterministic");
227+
228+
assertNotNull(first.nodes());
229+
assertNotNull(second.nodes());
230+
List<String> firstIds = first.nodes().stream()
231+
.map(CodeNode::getId).sorted().toList();
232+
List<String> secondIds = second.nodes().stream()
233+
.map(CodeNode::getId).sorted().toList();
234+
assertEquals(firstIds, secondIds,
235+
"Node IDs should be identical across runs");
236+
}
237+
}

0 commit comments

Comments
 (0)