diff --git a/PLAN.md b/PLAN.md index 29a162a..ce902f6 100644 --- a/PLAN.md +++ b/PLAN.md @@ -561,12 +561,12 @@ Ta sekcja jest pisana pod **mały lokalny model** o ograniczonym kontekście. Ka Po ukończeniu zadania agent zmienia jego status w liście poniżej i dopisuje jedną linię do dziennika. -- [ ] T1 Deduplicator compile fix +- [x] T1 Deduplicator compile fix - [x] T2 NameNormalizer testy - [ ] T3 PartyNormalizer testy - [x] T4 MarkdownRegistrySource test - [x] T5 Canonical round-trip -- [ ] T6 GraphLoader idempotencja [NEO4J] +- [~] T6 GraphLoader idempotencja [NEO4J] (skipped: Docker API too old) - [ ] T7 GraphValidator + CSV [NEO4J] - [ ] T8 Zielony pełny build diff --git a/szpitale-graph/local-agent-progress.json b/szpitale-graph/local-agent-progress.json index 51b2dd8..5c7b87f 100644 --- a/szpitale-graph/local-agent-progress.json +++ b/szpitale-graph/local-agent-progress.json @@ -55,10 +55,10 @@ "id": "T6", "title": "GraphLoader idempotencja", "tag": "NEO4J", - "status": "in_progress", + "status": "skipped", "startedAt": "2026-07-07T00:00:00Z", - "finishedAt": null, - "note": "wymaga Dockera; bez -> skipped" + "finishedAt": "2026-07-07T00:00:00Z", + "note": "Docker API version mismatch: client 1.32, min 1.44. Testcontainers cannot start." }, { "id": "T7", diff --git a/szpitale-graph/src/test/java/com/developx/szpitale/load/GraphLoaderIT.java b/szpitale-graph/src/test/java/com/developx/szpitale/load/GraphLoaderIT.java new file mode 100644 index 0000000..0be218a --- /dev/null +++ b/szpitale-graph/src/test/java/com/developx/szpitale/load/GraphLoaderIT.java @@ -0,0 +1,115 @@ +package com.developx.szpitale.load; + +import com.developx.szpitale.model.*; +import com.developx.szpitale.model.enums.*; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.neo4j.driver.*; +import org.testcontainers.containers.Neo4jContainer; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +class GraphLoaderIT { + + private static Neo4jContainer neo4j; + private static Driver driver; + + @BeforeAll + static void setup() { + neo4j = new Neo4jContainer<>("neo4j:5") + .withEnv("NEO4J_AUTH", "neo4j/password"); + neo4j.start(); + driver = GraphDatabase.driver( + neo4j.getBoltUrl(), + AuthTokens.basic("neo4j", "password") + ); + } + + @AfterAll + static void teardown() { + if (driver != null) driver.close(); + if (neo4j != null) neo4j.close(); + } + + @Test + void load_twice_isIdempotent() { + GraphSchema schema = new GraphSchema(driver); + schema.createConstraints(); + + Hospital hospital = new Hospital( + "hosp:test:test-szpital", + "Test Szpital", + "TS", + "TestCity", + "test", + LegalForm.SPZOZ, + "Tester", + SupervisoryBodyType.RADA_SPOLECZNA, + null, null, "https://test.pl", + List.of("https://test.pl") + ); + + Person person = new Person( + "person:test-osoba", + "Test Osoba", + "Dyrektor", + List.of(), + List.of("https://test.pl") + ); + + CanonicalDataset dataset = new CanonicalDataset( + "1.0", "test", + java.time.LocalDateTime.now(), + List.of(hospital), + List.of(person), + List.of(), + List.of(new Role( + "hosp:test:test-szpital", + "person:test-osoba", + RoleType.DYREKTOR, + "Dyrektor", + OrganType.DYREKCJA, + RoleStatus.AKTUALNY, + null, null, null, + List.of("https://test.pl") + )), + List.of() + ); + + GraphLoader loader = new GraphLoader(driver); + loader.load(List.of(dataset)); + loader.load(List.of(dataset)); + + try (Session session = driver.session()) { + String cypher = "MATCH (h:Hospital {id: \"hosp:test:test-szpital\"}) RETURN count(h) AS cnt"; + long hospitalCount = session.run(cypher).single().get("cnt").asInt(); + assertEquals(1, hospitalCount, "Should have exactly 1 hospital node after double load"); + + cypher = "MATCH (p:Person {id: \"person:test-osoba\"}) RETURN count(p) AS cnt"; + long personCount = session.run(cypher).single().get("cnt").asInt(); + assertEquals(1, personCount, "Should have exactly 1 person node after double load"); + } + } + + @Test + void schema_constraints_created() { + GraphSchema schema = new GraphSchema(driver); + schema.createConstraints(); + + try (Session session = driver.session()) { + session.run("CREATE (h:Hospital {id: \"cons-test\"})"); + + try { + session.run("CREATE (h:Hospital {id: \"cons-test\"})"); + fail("Should have thrown due to unique constraint"); + } catch (Exception e) { + assertTrue(e.getMessage().contains("constraint") || + e.getMessage().contains("already exists") || + e.getMessage().contains("UniqueProperties")); + } + } + } +} diff --git a/szpitale-graph/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst b/szpitale-graph/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst index e0e709d..4a2bb4b 100644 --- a/szpitale-graph/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst +++ b/szpitale-graph/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst @@ -2,4 +2,5 @@ com/developx/szpitale/ingest/normalize/NameNormalizerTest.class com/developx/szpitale/ingest/normalize/PartyNormalizerTest.class com/developx/szpitale/ingest/source/MarkdownRegistrySourceTest.class com/developx/szpitale/ingest/normalize/DeduplicatorTest.class +com/developx/szpitale/load/GraphLoaderIT.class com/developx/szpitale/load/CanonicalRoundTripTest.class diff --git a/szpitale-graph/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst b/szpitale-graph/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst index 7593483..7403611 100644 --- a/szpitale-graph/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst +++ b/szpitale-graph/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst @@ -3,3 +3,4 @@ /home/kruszewskia/Workspace/Private/Szpitale-graph/szpitale-graph/src/test/java/com/developx/szpitale/ingest/normalize/PartyNormalizerTest.java /home/kruszewskia/Workspace/Private/Szpitale-graph/szpitale-graph/src/test/java/com/developx/szpitale/ingest/source/MarkdownRegistrySourceTest.java /home/kruszewskia/Workspace/Private/Szpitale-graph/szpitale-graph/src/test/java/com/developx/szpitale/load/CanonicalRoundTripTest.java +/home/kruszewskia/Workspace/Private/Szpitale-graph/szpitale-graph/src/test/java/com/developx/szpitale/load/GraphLoaderIT.java diff --git a/szpitale-graph/target/surefire-reports/TEST-com.developx.szpitale.load.GraphLoaderIT.xml b/szpitale-graph/target/surefire-reports/TEST-com.developx.szpitale.load.GraphLoaderIT.xml new file mode 100644 index 0000000..1c63882 --- /dev/null +++ b/szpitale-graph/target/surefire-reports/TEST-com.developx.szpitale.load.GraphLoaderIT.xml @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/szpitale-graph/target/surefire-reports/com.developx.szpitale.load.GraphLoaderIT.txt b/szpitale-graph/target/surefire-reports/com.developx.szpitale.load.GraphLoaderIT.txt new file mode 100644 index 0000000..0a4623b --- /dev/null +++ b/szpitale-graph/target/surefire-reports/com.developx.szpitale.load.GraphLoaderIT.txt @@ -0,0 +1,18 @@ +------------------------------------------------------------------------------- +Test set: com.developx.szpitale.load.GraphLoaderIT +------------------------------------------------------------------------------- +Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.386 s <<< FAILURE! -- in com.developx.szpitale.load.GraphLoaderIT +com.developx.szpitale.load.GraphLoaderIT -- Time elapsed: 0.386 s <<< ERROR! +java.lang.IllegalStateException: Could not find a valid Docker environment. Please see logs and check configuration + at org.testcontainers.dockerclient.DockerClientProviderStrategy.lambda$getFirstValidStrategy$7(DockerClientProviderStrategy.java:274) + at java.base/java.util.Optional.orElseThrow(Optional.java:403) + at org.testcontainers.dockerclient.DockerClientProviderStrategy.getFirstValidStrategy(DockerClientProviderStrategy.java:265) + at org.testcontainers.DockerClientFactory.getOrInitializeStrategy(DockerClientFactory.java:154) + at org.testcontainers.DockerClientFactory.client(DockerClientFactory.java:196) + at org.testcontainers.DockerClientFactory$1.getDockerClient(DockerClientFactory.java:108) + at com.github.dockerjava.api.DockerClientDelegate.authConfig(DockerClientDelegate.java:109) + at org.testcontainers.containers.GenericContainer.start(GenericContainer.java:321) + at com.developx.szpitale.load.GraphLoaderIT.setup(GraphLoaderIT.java:24) + at java.base/java.lang.reflect.Method.invoke(Method.java:565) + at java.base/java.util.ArrayList.forEach(ArrayList.java:1604) + diff --git a/szpitale-graph/target/test-classes/com/developx/szpitale/load/GraphLoaderIT.class b/szpitale-graph/target/test-classes/com/developx/szpitale/load/GraphLoaderIT.class new file mode 100644 index 0000000..cd489d0 Binary files /dev/null and b/szpitale-graph/target/test-classes/com/developx/szpitale/load/GraphLoaderIT.class differ