diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 22e408c4c..e3d7fed6c 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -12,7 +12,7 @@ Test:
script:
- ./gradlew verify
artifacts:
+ when: always
reports:
junit:
- build/test-results/**/TEST-*.xml
-
diff --git a/CI/.morphic-gitlab-ci.yml b/CI/.morphic-gitlab-ci.yml
new file mode 100644
index 000000000..dfb17cdbe
--- /dev/null
+++ b/CI/.morphic-gitlab-ci.yml
@@ -0,0 +1,118 @@
+cache:
+ paths:
+ - .gradle/wrapper
+ - .gradle/caches
+
+before_script:
+ - echo "Performing build..."
+
+stages:
+ - build
+ - test
+ - package
+ - deploy
+
+variables:
+ AWS_DEFAULT_REGION: $AWS_DEFAULT_REGION
+ AWS_ACCESS_KEY_ID: $AWS_ACCESS_KEY_ID
+ AWS_SECRET_ACCESS_KEY: $AWS_SECRET_ACCESS_KEY
+ AWS_ACCOUNT_ID: $AWS_ACCOUNT_ID
+ EKS_CLUSTER_NAME: $EKS_CLUSTER_NAME
+ AWS_ACCESS_KEY_ID_PROD: $AWS_ACCESS_KEY_ID_PROD
+ AWS_SECRET_ACCESS_KEY_PROD: $AWS_SECRET_ACCESS_KEY_PROD
+ AWS_ACCOUNT_ID_PROD: $AWS_ACCOUNT_ID_PROD
+ EKS_CLUSTER_NAME_PROD: $EKS_CLUSTER_NAME_PROD
+
+build:
+ image: quay.io/ebi-ait/ingest-base-images:openjdk_11
+ stage: build
+ script:
+ - ./gradlew build -x test --info --stacktrace
+ artifacts:
+ paths:
+ - build/libs/*.jar
+
+test:
+ image: quay.io/ebi-ait/ingest-base-images:openjdk_11
+ stage: test
+ script:
+ - ./gradlew test
+ allow_failure: true
+ variables:
+ GRADLE_OPTS: "-Dorg.gradle.daemon=false"
+
+docker-build-dev:
+ stage: package
+ image: docker:19.03.12
+ services:
+ - docker:19.03.12-dind
+ before_script:
+ - apk add --update --no-cache python3 py3-pip
+ - pip3 install awscli
+ script:
+ - docker build -t ingest-core-morphic:$CI_COMMIT_SHA .
+ - aws ecr get-login-password --region $AWS_DEFAULT_REGION |
+ docker login --username AWS --password-stdin $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com
+ - docker tag ingest-core-morphic:$CI_COMMIT_SHA $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/ingest-core-morphic:$CI_COMMIT_SHA
+ - docker push $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/ingest-core-morphic:$CI_COMMIT_SHA
+
+docker-build-prod:
+ stage: package
+ image: docker:19.03.12
+ services:
+ - docker:19.03.12-dind
+ variables:
+ AWS_ACCESS_KEY_ID: $AWS_ACCESS_KEY_ID_PROD
+ AWS_SECRET_ACCESS_KEY: $AWS_SECRET_ACCESS_KEY_PROD
+ AWS_ACCOUNT_ID: $AWS_ACCOUNT_ID_PROD
+ EKS_CLUSTER_NAME: $EKS_CLUSTER_NAME_PROD
+ before_script:
+ - export AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID_PROD
+ - export AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY_PROD
+ - export AWS_ACCOUNT_ID=$AWS_ACCOUNT_ID_PROD
+ - apk add --update --no-cache python3 py3-pip
+ - pip3 install awscli
+ script:
+ - docker build -t ingest-core-morphic:$CI_COMMIT_SHA .
+ - aws ecr get-login-password --region $AWS_DEFAULT_REGION |
+ docker login --username AWS --password-stdin $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com
+ - docker tag ingest-core-morphic:$CI_COMMIT_SHA $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/ingest-core-morphic:$CI_COMMIT_SHA
+ - docker push $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/ingest-core-morphic:$CI_COMMIT_SHA
+
+deploy-dev:
+ stage: deploy
+ image: alpine/k8s:1.27.13
+ before_script:
+ - apk add --update --no-cache curl jq python3 py3-pip
+ - python3 -m venv /opt/venv
+ - source /opt/venv/bin/activate
+ - pip install awscli
+ - curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
+ - install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
+ - export AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID
+ - export AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY
+ - export AWS_DEFAULT_REGION=$AWS_DEFAULT_REGION
+ - aws eks update-kubeconfig --name $EKS_CLUSTER_NAME --region $AWS_DEFAULT_REGION
+ script:
+ - sed -i "s|{{IMAGE}}|$AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/ingest-core-morphic:$CI_COMMIT_SHA|g" CI/ingest-core-morphic-deployment-dev.yaml
+ - kubectl apply -f CI/ingest-core-morphic-deployment-dev.yaml
+ - kubectl apply -f CI/ingest-core-morphic-service.yaml -n morphic-dev
+
+deploy-prod:
+ stage: deploy
+ image: alpine/k8s:1.27.13
+ before_script:
+ - apk add --update --no-cache curl jq python3 py3-pip
+ - python3 -m venv /opt/venv
+ - source /opt/venv/bin/activate
+ - pip install awscli
+ - curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
+ - install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
+ - export AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID_PROD
+ - export AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY_PROD
+ - export AWS_DEFAULT_REGION=$AWS_DEFAULT_REGION
+ - aws eks update-kubeconfig --name $EKS_CLUSTER_NAME_PROD --region $AWS_DEFAULT_REGION
+ script:
+ - sed -i "s|{{IMAGE}}|$AWS_ACCOUNT_ID_PROD.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/ingest-core-morphic:$CI_COMMIT_SHA|g" CI/ingest-core-morphic-deployment-prod.yaml
+ - kubectl apply -f CI/ingest-core-morphic-deployment-prod.yaml
+ - kubectl apply -f CI/ingest-core-morphic-service.yaml -n morphic-prod
diff --git a/CI/ingest-core-morphic-deployment-dev.yaml b/CI/ingest-core-morphic-deployment-dev.yaml
new file mode 100644
index 000000000..174883f07
--- /dev/null
+++ b/CI/ingest-core-morphic-deployment-dev.yaml
@@ -0,0 +1,44 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: ingest-core-deployment
+ namespace: morphic-dev
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: ingest-core
+ template:
+ metadata:
+ labels:
+ app: ingest-core
+ spec:
+ containers:
+ - name: ingest-core-container
+ image: {{IMAGE}}
+ ports:
+ - containerPort: 8080
+ env:
+ - name: SPRING_PROFILES_ACTIVE
+ value: local
+ - name: MONGO_URI
+ value: mongodb+srv://morphic-dev:mDev12345@morphicdevcluster.jduoa8p.mongodb.net/MorphicDev?retryWrites=true&w=majority
+ - name: RABBIT_HOST
+ value: rabbitmq-service
+ - name: RABBIT_PORT
+ value: "5672"
+ - name: AWS_COGNITO_DOMAIN
+ value: "https://morphic-dev-2.auth.eu-west-2.amazoncognito.com/oauth2"
+ - name: AWS_ACCESS_KEY_ID
+ valueFrom:
+ secretKeyRef:
+ name: aws-credentials
+ key: AWS_ACCESS_KEY_ID
+ - name: AWS_SECRET_ACCESS_KEY
+ valueFrom:
+ secretKeyRef:
+ name: aws-credentials
+ key: AWS_SECRET_ACCESS_KEY
+ - name: AWS_REGION
+ value: eu-west-2 # Optionally specify AWS region as an environment variable
+ imagePullPolicy: Always
diff --git a/CI/ingest-core-morphic-deployment-prod.yaml b/CI/ingest-core-morphic-deployment-prod.yaml
new file mode 100644
index 000000000..55516c14e
--- /dev/null
+++ b/CI/ingest-core-morphic-deployment-prod.yaml
@@ -0,0 +1,44 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: ingest-core-deployment
+ namespace: morphic-prod
+spec:
+ replicas: 2
+ selector:
+ matchLabels:
+ app: ingest-core
+ template:
+ metadata:
+ labels:
+ app: ingest-core
+ spec:
+ containers:
+ - name: ingest-core-container
+ image: {{IMAGE}}
+ ports:
+ - containerPort: 8080
+ env:
+ - name: SPRING_PROFILES_ACTIVE
+ value: prod
+ - name: MONGO_URI
+ value: mongodb+srv://morphic-prod:morphicProd#12345@morphicprodcluster.gvr5bkw.mongodb.net/MorphicProd?retryWrites=true&w=majority
+ - name: RABBIT_HOST
+ value: rabbitmq-service
+ - name: RABBIT_PORT
+ value: "5672"
+ - name: AWS_COGNITO_DOMAIN
+ value: "https://morphic.auth.eu-west-2.amazoncognito.com/oauth2"
+ - name: AWS_ACCESS_KEY_ID
+ valueFrom:
+ secretKeyRef:
+ name: aws-credentials
+ key: AWS_ACCESS_KEY_ID
+ - name: AWS_SECRET_ACCESS_KEY
+ valueFrom:
+ secretKeyRef:
+ name: aws-credentials
+ key: AWS_SECRET_ACCESS_KEY
+ - name: AWS_REGION
+ value: eu-west-2 # Optionally specify AWS region as an environment variable
+ imagePullPolicy: Always
diff --git a/CI/ingest-core-morphic-service.yaml b/CI/ingest-core-morphic-service.yaml
new file mode 100644
index 000000000..98e6324a3
--- /dev/null
+++ b/CI/ingest-core-morphic-service.yaml
@@ -0,0 +1,17 @@
+apiVersion: v1
+kind: Service
+metadata:
+ name: ingest-core-service
+spec:
+ selector:
+ app: ingest-core
+ ports:
+ - name: http-ingest-core
+ protocol: TCP
+ port: 8080 # HTTP port
+ targetPort: 8080 # Should match the containerPort in the Deployment YAML
+ - name: https-ingest-core
+ protocol: TCP
+ port: 443 # HTTPS port
+ targetPort: 8080 # Should match the containerPort in the Deployment YAML
+ type: LoadBalancer
diff --git a/Dockerfile b/Dockerfile
index 123729ceb..3b2248718 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -19,6 +19,7 @@ ENV USR_AUTH_AUDIENCE=https://dev.data.humancellatlas.org/
ENV GCP_JWK_PROVIDER_BASE_URL=https://www.googleapis.com/service_accounts/v1/jwk/
ENV GCP_PROJECT_WHITELIST=hca-dcp-production.iam.gserviceaccount.com,human-cell-atlas-travis-test.iam.gserviceaccount.com,broad-dsde-mint-dev.iam.gserviceaccount.com,broad-dsde-mint-test.iam.gserviceaccount.com,broad-dsde-mint-staging.iam.gserviceaccount.com
ENV SCHEMA_BASE_URI=https://schema.dev.data.humancellatlas.org/
+ENV AWS_COGNITO_DOMAIN=https://morphic-dev.auth.eu-west-2.amazoncognito.com/oauth2
ADD gradle ./gradle
ADD src ./src
diff --git a/build.gradle b/build.gradle
index 14e5a4b8e..bb832e879 100644
--- a/build.gradle
+++ b/build.gradle
@@ -3,9 +3,11 @@ import org.gradle.api.tasks.testing.logging.TestExceptionFormat
plugins {
id 'org.springframework.boot' version '2.1.6.RELEASE'
id 'java'
+ id "com.diffplug.spotless" version "6.20.0"
}
apply plugin: 'io.spring.dependency-management'
+apply plugin: 'com.diffplug.spotless'
group = 'com.example'
version = '0.0.1-SNAPSHOT'
@@ -64,6 +66,14 @@ tasks.withType(Test) {
}
}
+spotless {
+ java {
+ googleJavaFormat()
+ removeUnusedImports()
+ importOrder 'java', 'javax', 'org', 'com'
+ }
+}
+
dependencies {
['actuator', 'data-rest', 'hateoas', 'security', 'web', 'webflux'].forEach {
implementation "org.springframework.boot:spring-boot-starter-${it}"
@@ -77,6 +87,7 @@ dependencies {
exclude group: 'org.mongodb', module: 'mongodb-driver'
}
implementation 'org.springframework.data:spring-data-rest-hal-browser'
+ implementation 'org.springframework.boot:spring-boot-starter-mail'
implementation 'org.springframework.retry:spring-retry:1.3.1'
implementation 'org.springframework:spring-aspects:5.3.13'
@@ -102,11 +113,15 @@ dependencies {
exclude group: 'org.mongodb', module: 'mongo-java-driver'
}
- compile 'org.projectreactor:reactor-spring:1.0.1.RELEASE'
- compile 'org.projectlombok:lombok'
+ implementation 'com.amazonaws:aws-java-sdk-s3:1.12.705'
+ /*implementation 'software.amazon.awssdk:sts:2.17.19'*/
+
+ implementation 'org.projectreactor:reactor-spring:1.0.1.RELEASE'
+ compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
+ testCompileOnly 'org.projectlombok:lombok'
testImplementation 'org.springframework.security:spring-security-test'
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.assertj', module: 'assertj-core'
diff --git a/docs/managed-access.md b/docs/managed-access.md
index 1533d234a..2c5356590 100644
--- a/docs/managed-access.md
+++ b/docs/managed-access.md
@@ -3,6 +3,12 @@
## Links
- [ticket 967](https://app.zenhub.com/workspaces/dcp-ingest-product-development-5f71ca62a3cb47326bdc1b5c/issues/gh/ebi-ait/dcp-ingest-central/967)
+## Terms
+
+* ACL - Access Control List
+* DAC - Data Access Committee
+
+## API Access Control Flow
```mermaid
sequenceDiagram
@@ -10,28 +16,117 @@ sequenceDiagram
participant api
participant authorization_service
participant operation_service
+ participant audit_service
autonumber
client ->> api: api operation
note over authorization_service: new service, query
snapshot of DAC
- api ->> authorization_service: operation allowed for
user and document?
-
- authorization_service -->> api: true
-
+ par new
+ api ->> authorization_service: operation allowed for
user and document?
+ authorization_service -->> api: true
+ api ->> audit_service: record operation
+ end
api ->> operation_service: perform operation
```
+## API Access Control - Details
+There are 2 options here:
+1. return all records from DB & filter the output to keep the allowed records
+2. instrument the query and add a criteria to return only allowed records
+
+For 1st iteration, we'll go with option 1, which is easier to implement, but might
+perform worse for large collections.
+
+```mermaid
+sequenceDiagram
+ title 1. filter DB result
+ participant client
+ participant Controller
+ participant Repository
+ participant RowLevelSecurityAspect
+ participant DB
+ participant Authentication
+ participant MetadataDocument
+
+ autonumber
+
+ client ->> Controller: api resource
+ note over Controller: GET /files
+ Controller ->> Repository: findAll()
+ note over Repository: anotated with @RowLevelSecurity
+ Repository ->> DB: execute query
+ DB -->> RowLevelSecurityAspect: db result (collection)
+ note over RowLevelSecurityAspect: implement as an AOP Advice
to the Repository
+ RowLevelSecurityAspect ->> Authentication: get user roles
+ RowLevelSecurityAspect ->> MetadataDocument: get project uuid
+ RowLevelSecurityAspect ->> RowLevelSecurityAspect: filter, keep allowed
+ RowLevelSecurityAspect -->> Repository: filtered result
+ Repository -->> Controller: filtered result
+ Controller -->> client: api response
+```
+
+## ACL Update Flow
```mermaid
sequenceDiagram
- participant authorization_update_service
- participant dac
-
- note left of dac: periodic update job
interface not clear yet
- authorization_update_service ->> dac: snapshot access lists
- authorization_update_service ->> authorization_update_service: update records
+ participant contributor
+ participant DACO
+ participant authorization_update_service
+
+ par application for access
+ contributor ->> DACO: apply for upload
permissions to dataset
+ note left of DACO: name, email, project
+ DACO ->> DACO: assess, compare
to signed docs,
approve
+ end
+ par get ACL data into ingest
+ note right of DACO: periodic updates
interface not clear yet,
initially email
+ DACO ->> authorization_update_service: update ACL for project
+ authorization_update_service ->> ingest_db: update records
+ note over ingest_db: update roles list,
ACL audit table
+ end
```
+## Representing ACLs in ingest
+
+There are 2 options to consider. We will proceed with option 1.
+1. Store a list of allowed datasets for each user, in addition to the
+ wrangler or contributor roles
+```mermaid
+classDiagram
+ direction LR
+ class User {
+ username
+ }
+ class Role {
+ name
+ }
+ User --> "1..*" Role : roles
+ note for Role "Wrangler, Contrbutor, Dataset A, Dataset B"
+```
+2. Store a list of allowed users for each dataset.
+
+```mermaid
+classDiagram
+ direction LR
+
+ class Project {
+ content
+ }
+ class User {
+ name
+ roles
+ }
+ Project --> "1..*" User : allowed_users
+```
+
+```mermaid
+graph RL
+
+ A:::someclass --> B
+ classDef someclass fill:#f96;
+ linkStyle default fill:none,stroke-width:3px,stroke:red
+
+```
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 2d3811096..5b500a503 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -3,4 +3,5 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip
+
diff --git a/src/integration/java/org/humancellatlas/ingest/AuditEntryTest.java b/src/integration/java/org/humancellatlas/ingest/AuditEntryTest.java
deleted file mode 100644
index 8d5c443d7..000000000
--- a/src/integration/java/org/humancellatlas/ingest/AuditEntryTest.java
+++ /dev/null
@@ -1,97 +0,0 @@
-package org.humancellatlas.ingest;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import org.humancellatlas.ingest.audit.AuditEntry;
-import org.humancellatlas.ingest.audit.AuditEntryRepository;
-import org.humancellatlas.ingest.audit.AuditEntryService;
-import org.humancellatlas.ingest.audit.AuditType;
-import org.humancellatlas.ingest.bundle.BundleManifestRepository;
-import org.humancellatlas.ingest.config.MigrationConfiguration;
-import org.humancellatlas.ingest.core.service.MetadataCrudService;
-import org.humancellatlas.ingest.core.service.MetadataUpdateService;
-import org.humancellatlas.ingest.project.*;
-import org.humancellatlas.ingest.schemas.SchemaService;
-import org.humancellatlas.ingest.submission.SubmissionEnvelopeRepository;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.Test;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.boot.test.mock.mockito.MockBean;
-import org.springframework.data.mongodb.core.MongoTemplate;
-import org.springframework.security.test.context.support.WithMockUser;
-
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-@SpringBootTest
-public class AuditEntryTest {
- @Autowired
- private ProjectService projectService;
-
- @Autowired
- private AuditEntryService auditEntryService;
-
- @Autowired
- private MongoTemplate mongoTemplate;
-
- @Autowired
- private AuditEntryRepository auditEntryRepository;
-
- @MockBean
- private SubmissionEnvelopeRepository submissionEnvelopeRepository;
-
- @MockBean
- private ProjectRepository projectRepository;
-
- @MockBean
- private MetadataCrudService metadataCrudService;
-
- @MockBean
- private MetadataUpdateService metadataUpdateService;
-
- @MockBean
- private SchemaService schemaService;
-
- @MockBean
- private BundleManifestRepository bundleManifestRepository;
-
- @MockBean
- private ProjectEventHandler projectEventHandler;
-
- @MockBean
- MigrationConfiguration migrationConfiguration;
-
-
- @Test
- @WithMockUser(value = "test_user")
- void testAuditEntryGenerationOnProjectStateUpdate() {
- //given
- WranglingState initialWranglingState = WranglingState.NEW;
- Project project = new Project("{\"name\": \"Project 1\"}");
- project.setWranglingState(initialWranglingState);
- this.mongoTemplate.save(project);
-
- // when
- WranglingState updatedWranglingState = WranglingState.ELIGIBLE;
- ObjectNode patchUpdate = new ObjectMapper()
- .createObjectNode()
- .put("wranglingState", updatedWranglingState.getValue());
- projectService.update(project, patchUpdate, false);
-
- // then
- AuditEntry actual = projectService.getProjectAuditEntries(project).get(0);
-
- assertThat(actual)
- .hasFieldOrPropertyWithValue("auditType", AuditType.STATUS_UPDATED)
- .hasFieldOrPropertyWithValue("before", initialWranglingState.name())
- .hasFieldOrPropertyWithValue("after", updatedWranglingState.name())
- .returns(true, e->e.getUser().contains("Username: test_user;"));
- }
-
- @AfterEach
- private void tearDown() {
- this.mongoTemplate.dropCollection(Project.class);
- this.mongoTemplate.dropCollection(AuditEntry.class);
- }
-}
diff --git a/src/integration/java/org/humancellatlas/ingest/IngestCoreApplicationTests.java b/src/integration/java/org/humancellatlas/ingest/IngestCoreApplicationTests.java
deleted file mode 100644
index 62c080084..000000000
--- a/src/integration/java/org/humancellatlas/ingest/IngestCoreApplicationTests.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package org.humancellatlas.ingest;
-
-import org.humancellatlas.ingest.config.MigrationConfiguration;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.boot.test.mock.mockito.MockBean;
-import org.springframework.test.context.junit.jupiter.SpringExtension;
-
-@SpringBootTest
-public class IngestCoreApplicationTests {
- @MockBean
- MigrationConfiguration migrationConfiguration;
-
- @Test
- public void contextLoads() {
- }
-
-}
diff --git a/src/integration/java/org/humancellatlas/ingest/MongoAuditingTest.java b/src/integration/java/org/humancellatlas/ingest/MongoAuditingTest.java
deleted file mode 100644
index 8e710d92b..000000000
--- a/src/integration/java/org/humancellatlas/ingest/MongoAuditingTest.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package org.humancellatlas.ingest;
-
-import org.humancellatlas.ingest.config.MigrationConfiguration;
-import org.humancellatlas.ingest.project.Project;
-import org.humancellatlas.ingest.project.ProjectRepository;
-import org.junit.jupiter.api.Test;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.boot.test.mock.mockito.MockBean;
-import org.springframework.security.test.context.support.WithMockUser;
-
-import java.util.HashMap;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-@SpringBootTest
-public class MongoAuditingTest {
-
- @MockBean
- private MigrationConfiguration migrationConfiguration;
-
- @Autowired
- private ProjectRepository projectRepository;
-
- @Test
- @WithMockUser("johndoe")
- public void auditMongoRecord() {
- //given:
- Project project = new Project(new HashMap<>());
-
- //when:
- Project persistentProject = projectRepository.save(project);
-
- //then:
- /* NOTE there doesn't seem to be a clean and easy way to check this without updating the UserAuditing class
- itself to assume that the default principal type contains username and password. */
- assertThat(persistentProject.getUser()).contains("johndoe");
- }
-
-}
diff --git a/src/integration/java/org/humancellatlas/ingest/archiving/web/ArchiveJobControllerTest.java b/src/integration/java/org/humancellatlas/ingest/archiving/web/ArchiveJobControllerTest.java
deleted file mode 100644
index b806f860b..000000000
--- a/src/integration/java/org/humancellatlas/ingest/archiving/web/ArchiveJobControllerTest.java
+++ /dev/null
@@ -1,138 +0,0 @@
-package org.humancellatlas.ingest.archiving.web;
-
-import org.humancellatlas.ingest.archiving.entity.ArchiveJob;
-import org.humancellatlas.ingest.archiving.entity.ArchiveJobRepository;
-import org.humancellatlas.ingest.config.MigrationConfiguration;
-import org.junit.jupiter.api.Test;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.autoconfigure.data.mongo.AutoConfigureDataMongo;
-import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.boot.test.mock.mockito.MockBean;
-import org.springframework.http.MediaType;
-import org.springframework.security.test.context.support.WithMockUser;
-import org.springframework.test.web.servlet.MockMvc;
-
-import java.time.Instant;
-import java.util.*;
-
-import static org.hamcrest.Matchers.is;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.BDDMockito.given;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
-import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
-
-@SpringBootTest
-@AutoConfigureDataMongo()
-@AutoConfigureMockMvc
-public class ArchiveJobControllerTest {
-
- @Autowired
- MockMvc mockMvc;
-
- @MockBean
- private MigrationConfiguration migrationConfiguration;
-
- @MockBean
- private ArchiveJobRepository archiveJobRepository;
-
- private static final ArchiveJob.ArchiveJobStatus PENDING_STATUS = ArchiveJob.ArchiveJobStatus.PENDING;
- private static final ArchiveJob.ArchiveJobStatus COMPLETED_STATUS = ArchiveJob.ArchiveJobStatus.COMPLETED;
-
- private UUID uuid;
-
- private static final String ARCHIVE_JOB_ID = "1";
- private static final String SUBMISSION_UUID = "1234";
-
-
- @Test
- public void when_request_archive_job_creation_returns_successful_response() throws Exception {
- final ArchiveJob anArchiveJobById = createAnArchiveJob(ARCHIVE_JOB_ID, SUBMISSION_UUID, PENDING_STATUS);
-
- given(this.archiveJobRepository.save(any()))
- .willReturn(anArchiveJobById);
-
- this.mockMvc.perform(post("/archiveJobs")
- .contentType(MediaType.APPLICATION_JSON)
- .content(String.format("{\"submissionUuid\": \"%s\"}", this.uuid)))
- .andDo(print())
- .andExpect(status().isCreated())
- .andExpect(content().contentType(MediaType.APPLICATION_JSON))
- .andExpect(jsonPath("$.submissionUuid", is(SUBMISSION_UUID)))
- .andExpect(jsonPath("$.overallStatus", is(PENDING_STATUS.toString())))
- .andExpect(jsonPath("$.createdDate").isNotEmpty())
- .andReturn();
- }
-
- @Test
- @WithMockUser
- public void when_requesting_non_existing_archiving_job_returns_not_found_response() throws Exception {
- given(this.archiveJobRepository.findById(ARCHIVE_JOB_ID))
- .willReturn(Optional.empty());
-
- this.mockMvc.perform(get("/archiveJobs/{id}", ARCHIVE_JOB_ID)
- .contentType(MediaType.APPLICATION_JSON))
- .andDo(print())
- .andExpect(status().isNotFound())
- .andReturn();
- }
-
- @Test
- @WithMockUser
- public void when_existing_archiving_job_in_pending_status_returns_valid_response() throws Exception {
- final ArchiveJob anArchiveJob = createAnArchiveJob(ARCHIVE_JOB_ID, SUBMISSION_UUID, PENDING_STATUS);
-
- given(this.archiveJobRepository.findById(ARCHIVE_JOB_ID))
- .willReturn(Optional.of(anArchiveJob));
-
- this.mockMvc.perform(get("/archiveJobs/{id}", ARCHIVE_JOB_ID)
- .contentType(MediaType.APPLICATION_JSON))
- .andDo(print())
- .andExpect(status().isOk())
- .andExpect(jsonPath("$.submissionUuid", is(SUBMISSION_UUID)))
- .andExpect(jsonPath("$.overallStatus", is(PENDING_STATUS.toString())))
- .andExpect(jsonPath("$.createdDate").isNotEmpty())
- .andExpect(jsonPath("$.resultsFromArchives").doesNotExist())
- .andReturn();
- }
-
- @Test
- @WithMockUser
- public void when_existing_archiving_job_in_completed_status_returns_valid_response() throws Exception {
- final ArchiveJob anArchiveJob = createAnArchiveJob(ARCHIVE_JOB_ID, SUBMISSION_UUID, COMPLETED_STATUS);
- setArchiveResult(anArchiveJob);
-
- given(this.archiveJobRepository.findById(ARCHIVE_JOB_ID))
- .willReturn(Optional.of(anArchiveJob));
-
- this.mockMvc.perform(get("/archiveJobs/{id}", ARCHIVE_JOB_ID)
- .contentType(MediaType.APPLICATION_JSON))
- .andDo(print())
- .andExpect(status().isOk())
- .andExpect(jsonPath("$.submissionUuid", is(SUBMISSION_UUID)))
- .andExpect(jsonPath("$.overallStatus", is(COMPLETED_STATUS.toString())))
- .andExpect(jsonPath("$.createdDate").isNotEmpty())
- .andExpect(jsonPath("$.resultsFromArchives").isNotEmpty())
- .andReturn();
- }
-
- private ArchiveJob createAnArchiveJob(String id, String submissionUuid, ArchiveJob.ArchiveJobStatus status) {
- ArchiveJob archiveJob = new ArchiveJob();
- archiveJob.setId(ARCHIVE_JOB_ID);
- archiveJob.setCreatedDate(Instant.now());
- archiveJob.setOverallStatus(status);
- archiveJob.setSubmissionUuid(submissionUuid);
-
- return archiveJob;
- }
-
- private void setArchiveResult(ArchiveJob anArchiveJob) {
- Map resultByArchive = new HashMap<>();
- Map>> experimentsResult = new HashMap<>();
- experimentsResult.put("experiments", List.of(Map.of("accession", "1234"), Map.of("uuid", "1-2-3-4")));
- resultByArchive.put("hca_assays", experimentsResult);
- anArchiveJob.setResultsFromArchives(resultByArchive);
- }
-}
diff --git a/src/integration/java/org/humancellatlas/ingest/biomaterial/BiomaterialControllerTest.java b/src/integration/java/org/humancellatlas/ingest/biomaterial/BiomaterialControllerTest.java
deleted file mode 100644
index 329ed412b..000000000
--- a/src/integration/java/org/humancellatlas/ingest/biomaterial/BiomaterialControllerTest.java
+++ /dev/null
@@ -1,308 +0,0 @@
-package org.humancellatlas.ingest.biomaterial;
-
-import org.humancellatlas.ingest.config.MigrationConfiguration;
-import org.humancellatlas.ingest.core.MetadataDocument;
-import org.humancellatlas.ingest.core.Uuid;
-import org.humancellatlas.ingest.core.service.ValidationStateChangeService;
-import org.humancellatlas.ingest.messaging.MessageRouter;
-import org.humancellatlas.ingest.process.Process;
-import org.humancellatlas.ingest.process.ProcessRepository;
-import org.humancellatlas.ingest.project.Project;
-import org.humancellatlas.ingest.project.ProjectRepository;
-import org.humancellatlas.ingest.state.SubmissionState;
-import org.humancellatlas.ingest.state.ValidationState;
-import org.humancellatlas.ingest.submission.SubmissionEnvelope;
-import org.humancellatlas.ingest.submission.SubmissionEnvelopeRepository;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.autoconfigure.data.mongo.AutoConfigureDataMongo;
-import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.boot.test.mock.mockito.MockBean;
-import org.springframework.http.MediaType;
-import org.springframework.test.web.servlet.MockMvc;
-import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
-import org.springframework.web.util.UriComponentsBuilder;
-
-import java.util.Arrays;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
-
-@SpringBootTest
-@AutoConfigureDataMongo()
-@AutoConfigureMockMvc(printOnlyOnFailure = false)
-public class BiomaterialControllerTest {
-
- @MockBean
- ValidationStateChangeService validationStateChangeService;
-
- @Autowired
- private MockMvc webApp;
-
- @Autowired
- private ProcessRepository processRepository;
-
- @Autowired
- private BiomaterialRepository biomaterialRepository;
-
- @Autowired
- private SubmissionEnvelopeRepository submissionEnvelopeRepository;
-
- @Autowired
- private ProjectRepository projectRepository;
-
- @MockBean
- private MigrationConfiguration migrationConfiguration;
-
- @MockBean
- private MessageRouter messageRouter;
-
- Process process1;
-
- Process process2;
-
- Process process3;
-
- Biomaterial biomaterial;
-
- UriComponentsBuilder uriBuilder;
-
- SubmissionEnvelope submissionEnvelope;
-
- Project project;
-
- @BeforeEach
- void setUp() {
- submissionEnvelope = new SubmissionEnvelope();
- submissionEnvelope.setUuid(Uuid.newUuid());
- submissionEnvelope.enactStateTransition(SubmissionState.GRAPH_VALID);
- submissionEnvelope = submissionEnvelopeRepository.save(submissionEnvelope);
-
- project = new Project(null);
- project.getSubmissionEnvelopes().add(submissionEnvelope);
- project = projectRepository.save(project);
-
- process1 = processRepository.save(new Process(null));
- process2 = processRepository.save(new Process(null));
- process3 = processRepository.save(new Process(null));
-
- biomaterial = new Biomaterial();
- biomaterial.setSubmissionEnvelope(submissionEnvelope);
- biomaterial = biomaterialRepository.save(biomaterial);
-
- uriBuilder = ServletUriComponentsBuilder.fromCurrentContextPath();
- }
-
- @AfterEach
- void tearDown() {
- processRepository.deleteAll();
- biomaterialRepository.deleteAll();
- submissionEnvelopeRepository.deleteAll();
- projectRepository.deleteAll();
- }
-
- @Test
- public void newBiomaterialInSubmissionLinksToSubmissionAndProject() throws Exception {
- //given
- biomaterialRepository.deleteAll();
- processRepository.deleteAll();
-
- // when
- webApp.perform(
- post("/submissionEnvelopes/{id}/biomaterials", submissionEnvelope.getId())
- .contentType(MediaType.APPLICATION_JSON)
- .content("{\"content\": {}}")
- ).andExpect(status().isAccepted());
-
- //then
- assertThat(biomaterialRepository.findAll()).hasSize(1);
- assertThat(biomaterialRepository.findAllBySubmissionEnvelope(submissionEnvelope)).hasSize(1);
- assertThat(biomaterialRepository.findByProject(project)).hasSize(1);
-
- var newBiomaterial = biomaterialRepository.findAll().get(0);
- assertThat(newBiomaterial.getSubmissionEnvelope().getId()).isEqualTo(submissionEnvelope.getId());
- assertThat(newBiomaterial.getProject().getId()).isEqualTo(project.getId());
- assertThat(newBiomaterial.getProjects()).hasSize(1);
- assertThat(newBiomaterial.getProjects().stream().findFirst().get().getId()).isEqualTo(project.getId());
- }
-
- @Test
- public void newBiomaterialInSubmissionDoesNotFailIfSubmissionHasNoProject() throws Exception {
- //given
- biomaterialRepository.deleteAll();
- processRepository.deleteAll();
- projectRepository.deleteAll();
-
- // when
- webApp.perform(
- post("/submissionEnvelopes/{id}/biomaterials", submissionEnvelope.getId())
- .contentType(MediaType.APPLICATION_JSON)
- .content("{\"content\": {}}")
- ).andExpect(status().isAccepted());
-
- //then
- assertThat(biomaterialRepository.findAll()).hasSize(1);
- assertThat(biomaterialRepository.findAllBySubmissionEnvelope(submissionEnvelope)).hasSize(1);
-
- var newBiomaterial = biomaterialRepository.findAll().get(0);
- assertThat(newBiomaterial.getSubmissionEnvelope().getId()).isEqualTo(submissionEnvelope.getId());
- assertThat(newBiomaterial.getProject()).isNull();
- assertThat(newBiomaterial.getProjects()).isEmpty();
- }
-
- @Test
- public void testLinkBiomaterialAsInputToProcessesUsingPostMethodWithManyProcessesInPayload() throws Exception {
- // when
- webApp.perform(post("/biomaterials/{id}/inputToProcesses/", biomaterial.getId())
- .contentType("text/uri-list")
- .content(uriBuilder.build().toUriString() + "/processes/" + process1.getId()
- + '\n' + uriBuilder.build().toUriString() + "/processes/" + process2.getId()))
- .andExpect(status().isOk());
-
- // then
- verifyThatValidationStateChangedToDraftWhenGraphValid(biomaterial);
- Biomaterial updatedBiomaterial = biomaterialRepository.findById(biomaterial.getId()).get();
- assertThat(updatedBiomaterial.getInputToProcesses())
- .usingElementComparatorOnFields("id")
- .containsExactly(process1, process2);
- }
-
- @Test
- public void testLinkBiomaterialAsInputToProcessesUsingPutMethodWithManyProcessesInPayload() throws Exception {
- // given
- biomaterial.addAsInputToProcess(process1);
- biomaterialRepository.save(biomaterial);
-
- // when
- webApp.perform(put("/biomaterials/{id}/inputToProcesses/", biomaterial.getId())
- .contentType("text/uri-list")
- .content(uriBuilder.build().toUriString() + "/processes/" + process2.getId()
- + '\n' + uriBuilder.build().toUriString() + "/processes/" + process3.getId()))
- .andExpect(status().isOk());
-
- // then
- verifyThatValidationStateChangedToDraftWhenGraphValid(biomaterial);
- Biomaterial updatedBiomaterial = biomaterialRepository.findById(biomaterial.getId()).get();
- assertThat(updatedBiomaterial.getInputToProcesses())
- .usingElementComparatorOnFields("id")
- .containsExactly(process2, process3);
- }
-
-
- @Test
- public void testLinkBiomaterialAsInputToProcessesUsingPostMethodWithOneProcessInPayload() throws Exception {
- //when
- webApp.perform(post("/biomaterials/{id}/inputToProcesses/", biomaterial.getId())
- .contentType("text/uri-list")
- .content(uriBuilder.build().toUriString() + "/processes/" + process1.getId()))
- .andExpect(status().isOk());
-
- // then
- verifyThatValidationStateChangedToDraftWhenGraphValid(biomaterial);
- Biomaterial updatedBiomaterial = biomaterialRepository.findById(biomaterial.getId()).get();
- assertThat(updatedBiomaterial.getInputToProcesses())
- .usingElementComparatorOnFields("id")
- .containsExactly(process1);
- }
-
- @Test
- public void testLinkBiomaterialAsDerivedByProcessesUsingPostMethodWithManyProcessesInPayload() throws Exception {
- // when
- webApp.perform(post("/biomaterials/{id}/derivedByProcesses/", biomaterial.getId())
- .contentType("text/uri-list")
- .content(uriBuilder.build().toUriString() + "/processes/" + process1.getId()
- + '\n' + uriBuilder.build().toUriString() + "/processes/" + process2.getId()))
- .andExpect(status().isOk());
-
- // then
- verifyThatValidationStateChangedToDraftWhenGraphValid(biomaterial);
- Biomaterial updatedBiomaterial = biomaterialRepository.findById(biomaterial.getId()).get();
- assertThat(updatedBiomaterial.getDerivedByProcesses())
- .usingElementComparatorOnFields("id")
- .containsExactly(process1, process2);
- }
-
- @Test
- public void testLinkBiomaterialAsDerivedByProcessesUsingPutMethodWithManyProcessesInPayload() throws Exception {
- // given
- biomaterial.addAsDerivedByProcess(process1);
- biomaterialRepository.save(biomaterial);
-
- // when
- webApp.perform(put("/biomaterials/{id}/derivedByProcesses/", biomaterial.getId())
- .contentType("text/uri-list")
- .content(uriBuilder.build().toUriString() + "/processes/" + process2.getId()
- + '\n' + uriBuilder.build().toUriString() + "/processes/" + process3.getId()))
- .andExpect(status().isOk());
-
- // then
- verifyThatValidationStateChangedToDraftWhenGraphValid(biomaterial);
- Biomaterial updatedBiomaterial = biomaterialRepository.findById(biomaterial.getId()).get();
- assertThat(updatedBiomaterial.getDerivedByProcesses())
- .usingElementComparatorOnFields("id")
- .containsExactly(process2, process3);
- }
-
- @Test
- public void testLinkBiomaterialAsDerivedByProcessesUsingPostMethodWithOneProcessInPayload() throws Exception {
- // when
- webApp.perform(post("/biomaterials/{id}/derivedByProcesses/", biomaterial.getId())
- .contentType("text/uri-list")
- .content(uriBuilder.build().toUriString() + "/processes/" + process1.getId()))
- .andExpect(status().isOk());
-
- verifyThatValidationStateChangedToDraftWhenGraphValid(biomaterial);
-
- // then
- Biomaterial updatedBiomaterial = biomaterialRepository.findById(biomaterial.getId()).get();
- assertThat(updatedBiomaterial.getDerivedByProcesses())
- .usingElementComparatorOnFields("id")
- .containsExactly(process1);
- }
-
- @Test
- public void testUnlinkBiomaterialAsInputToProcesses() throws Exception {
- // given
- biomaterial.addAsInputToProcess(process1);
- biomaterialRepository.save(biomaterial);
-
- // when
- webApp.perform(delete("/biomaterials/{id}/inputToProcesses/{processId}", biomaterial.getId(), process1.getId()))
- .andExpect(status().isNoContent());
-
- // then
- verifyThatValidationStateChangedToDraftWhenGraphValid(biomaterial);
-
- Biomaterial updatedBiomaterial = biomaterialRepository.findById(biomaterial.getId()).get();
- assertThat(updatedBiomaterial.getInputToProcesses()).doesNotContain(process1);
- }
-
- @Test
- public void testUnlinkBiomaterialAsDerivedByProcesses() throws Exception {
- // given
- biomaterial.addAsDerivedByProcess(process1);
- biomaterialRepository.save(biomaterial);
-
- // when
- webApp.perform(delete("/biomaterials/{id}/derivedByProcesses/{processId}", biomaterial.getId(), process1.getId()))
- .andExpect(status().isNoContent());
-
- // then
- verifyThatValidationStateChangedToDraftWhenGraphValid(biomaterial);
- Biomaterial updatedBiomaterial = biomaterialRepository.findById(biomaterial.getId()).get();
- assertThat(updatedBiomaterial.getDerivedByProcesses()).doesNotContain(process1);
- }
-
- private void verifyThatValidationStateChangedToDraftWhenGraphValid(MetadataDocument... values) {
- Arrays.stream(values).forEach(
- value -> verify(validationStateChangeService, times(1))
- .changeValidationState(value.getType(), value.getId(), ValidationState.DRAFT)
- );
- }
-}
\ No newline at end of file
diff --git a/src/integration/java/org/humancellatlas/ingest/export/job/ExportJobControllerTest.java b/src/integration/java/org/humancellatlas/ingest/export/job/ExportJobControllerTest.java
deleted file mode 100644
index 6f087e7cc..000000000
--- a/src/integration/java/org/humancellatlas/ingest/export/job/ExportJobControllerTest.java
+++ /dev/null
@@ -1,167 +0,0 @@
-package org.humancellatlas.ingest.export.job;
-
-import org.humancellatlas.ingest.config.MigrationConfiguration;
-import org.humancellatlas.ingest.core.Uuid;
-import org.humancellatlas.ingest.export.destination.ExportDestination;
-import org.humancellatlas.ingest.exporter.Exporter;
-import org.humancellatlas.ingest.state.SubmissionState;
-import org.humancellatlas.ingest.submission.SubmissionEnvelope;
-import org.humancellatlas.ingest.submission.SubmissionEnvelopeRepository;
-import org.json.simple.JSONObject;
-import org.junit.Ignore;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.mockito.ArgumentCaptor;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.autoconfigure.data.mongo.AutoConfigureDataMongo;
-import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.boot.test.mock.mockito.MockBean;
-import org.springframework.test.web.servlet.MockMvc;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.humancellatlas.ingest.export.destination.ExportDestinationName.DCP;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.*;
-import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
-
-@SpringBootTest
-@AutoConfigureDataMongo()
-@AutoConfigureMockMvc()
-public class ExportJobControllerTest {
- public static final String STARTED = "STARTED";
- public static final String COMPLETE = "COMPLETE";
- @Autowired
- private MockMvc webApp;
-
- @Autowired
- private SubmissionEnvelopeRepository submissionEnvelopeRepository;
-
- @Autowired
- private ExportJobRepository exportJobRepository;
-
- @Autowired
- private ExportJobService exportJobService;
-
- @MockBean
- private Exporter exporter;
-
- // Adding MigrationConfiguration as a MockBean is needed as otherwise MigrationConfiguration won't be initialised.
- @MockBean
- private MigrationConfiguration migrationConfiguration;
-
- SubmissionEnvelope submissionEnvelope;
-
- ExportJob exportJob;
-
- Uuid projectUuid;
-
- @BeforeEach
- void setUp() {
- submissionEnvelope = new SubmissionEnvelope();
- submissionEnvelope.setUuid(Uuid.newUuid());
- submissionEnvelope.enactStateTransition(SubmissionState.EXPORTING);
- submissionEnvelope = submissionEnvelopeRepository.save(submissionEnvelope);
-
- projectUuid = Uuid.newUuid();
- var destinationContext = new JSONObject();
- destinationContext.put("projectUuid", projectUuid);
-
- var exportJobContext = new JSONObject();
- exportJobContext.put("dataFileTransfer", false);
- exportJob = ExportJob.builder()
- .id("export-job-id")
- .submission(submissionEnvelope)
- .destination(new ExportDestination(DCP, "v2", destinationContext))
- .context(exportJobContext)
- .build();
- exportJob = exportJobRepository.save(exportJob);
- }
-
- @AfterEach
- void tearDown() {
- exportJobRepository.deleteAll();
- submissionEnvelopeRepository.deleteAll();
- reset(exporter);
- }
-
- @Test
- void testDataTransferCallbackOnlyProgressesOnComplete() throws Exception {
- webApp.perform(
- // when
- patch("/exportJobs/{id}/context", exportJob.getId())
- .contentType(APPLICATION_JSON_VALUE)
- .content("{\"dataFileTransfer\": \"" + STARTED + "\"}")
- ) // then
- .andExpect(status().isAccepted());
- verify(exporter, never()).generateSpreadsheet(any(ExportJob.class));
-
- var savedJob = exportJobRepository.findById(exportJob.getId()).orElseThrow();
- assertThat(savedJob.getContext().get("dataFileTransfer")).isEqualTo(STARTED);
- }
-
- @Ignore
- void testDataTransferCallbackEndpoint() throws Exception {
- webApp.perform(
- // when
- patch("/exportJobs/{id}/context", exportJob.getId())
- .contentType(APPLICATION_JSON_VALUE)
- .content("{\"dataFileTransfer\": \"" + COMPLETE + "\"}")
- ) // then
- .andExpect(status().isAccepted());
- var argumentCaptor = ArgumentCaptor.forClass(ExportJob.class);
- verify(exporter).generateSpreadsheet(argumentCaptor.capture());
-
- var capturedArgument = argumentCaptor.getValue();
- assertThat(capturedArgument.getId()).isEqualTo(exportJob.getId());
- assertThat(capturedArgument.getDestination().getContext().get("projectUuid")).isEqualTo(projectUuid);
- assertThat(capturedArgument.getContext().get("dataFileTransfer")).isEqualTo(COMPLETE);
- }
-
- @Test
- void testSpreadsheetGenerationCallbackOnlyProgressesOnComplete() throws Exception {
- // given
- exportJob.getContext().put("dataFileTransfer", COMPLETE);
- exportJob = exportJobRepository.save(exportJob);
-
- webApp.perform(
- // when
- patch("/exportJobs/{id}/context", exportJob.getId())
- .contentType(APPLICATION_JSON_VALUE)
- .content("{\"spreadsheetGeneration\": \"" + STARTED + "\"}")
- ) // then
- .andExpect(status().isAccepted());
- verify(exporter, never()).exportMetadata(any(ExportJob.class));
-
- var savedJob = exportJobRepository.findById(exportJob.getId()).orElseThrow();
- assertThat(savedJob.getContext().get("dataFileTransfer")).isEqualTo(COMPLETE);
- assertThat(savedJob.getContext().get("spreadsheetGeneration")).isEqualTo(STARTED);
- }
-
- @Ignore
- void testSpreadsheetGenerationCallbackEndpoint() throws Exception {
- // given
- exportJob.getContext().put("dataFileTransfer", COMPLETE);
- exportJob.getContext().put("spreadsheetGeneration", STARTED);
- exportJob = exportJobRepository.save(exportJob);
-
- webApp.perform(
- // when
- patch("/exportJobs/{id}/context", exportJob.getId())
- .contentType(APPLICATION_JSON_VALUE)
- .content("{\"spreadsheetGeneration\": \"" + COMPLETE + "\"}")
- ) // then
- .andExpect(status().isAccepted());
- var argumentCaptor = ArgumentCaptor.forClass(ExportJob.class);
- verify(exporter).exportMetadata(argumentCaptor.capture());
-
- var capturedArgument = argumentCaptor.getValue();
- assertThat(capturedArgument.getId()).isEqualTo(exportJob.getId());
- assertThat(capturedArgument.getDestination().getContext().get("projectUuid")).isEqualTo(projectUuid);
- assertThat(capturedArgument.getContext().get("dataFileTransfer")).isEqualTo(COMPLETE);
- assertThat(capturedArgument.getContext().get("spreadsheetGeneration")).isEqualTo(COMPLETE);
- }
-}
diff --git a/src/integration/java/org/humancellatlas/ingest/file/FileControllerTest.java b/src/integration/java/org/humancellatlas/ingest/file/FileControllerTest.java
deleted file mode 100644
index 40c519f66..000000000
--- a/src/integration/java/org/humancellatlas/ingest/file/FileControllerTest.java
+++ /dev/null
@@ -1,384 +0,0 @@
-package org.humancellatlas.ingest.file;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import org.humancellatlas.ingest.config.MigrationConfiguration;
-import org.humancellatlas.ingest.core.MetadataDocument;
-import org.humancellatlas.ingest.core.Uuid;
-import org.humancellatlas.ingest.core.service.ValidationStateChangeService;
-import org.humancellatlas.ingest.messaging.MessageRouter;
-import org.humancellatlas.ingest.process.Process;
-import org.humancellatlas.ingest.process.ProcessRepository;
-import org.humancellatlas.ingest.project.Project;
-import org.humancellatlas.ingest.project.ProjectRepository;
-import org.humancellatlas.ingest.state.SubmissionState;
-import org.humancellatlas.ingest.state.ValidationState;
-import org.humancellatlas.ingest.submission.SubmissionEnvelope;
-import org.humancellatlas.ingest.submission.SubmissionEnvelopeRepository;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.autoconfigure.data.mongo.AutoConfigureDataMongo;
-import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.boot.test.mock.mockito.MockBean;
-import org.springframework.http.MediaType;
-import org.springframework.mock.web.MockHttpServletResponse;
-import org.springframework.test.web.servlet.MockMvc;
-import org.springframework.test.web.servlet.MvcResult;
-import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
-import org.springframework.web.util.UriComponentsBuilder;
-
-import java.util.Arrays;
-import java.util.UUID;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
-
-@SpringBootTest
-@AutoConfigureDataMongo()
-@AutoConfigureMockMvc(printOnlyOnFailure = false)
-public class FileControllerTest {
- @MockBean
- ValidationStateChangeService validationStateChangeService;
-
- @Autowired
- private MockMvc webApp;
-
- @Autowired
- private ProcessRepository processRepository;
-
- @Autowired
- private SubmissionEnvelopeRepository submissionEnvelopeRepository;
-
- @Autowired
- private FileRepository fileRepository;
-
- @Autowired
- private ProjectRepository projectRepository;
-
- @Autowired
- private ObjectMapper objectMapper;
-
- @MockBean
- private MigrationConfiguration migrationConfiguration;
-
- @MockBean
- private MessageRouter messageRouter;
-
- Process process1;
-
- Process process2;
-
- Process process3;
-
- File file;
-
- UriComponentsBuilder uriBuilder;
-
- SubmissionEnvelope submissionEnvelope;
-
- Project project;
-
- @BeforeEach
- void setUp() {
- submissionEnvelope = new SubmissionEnvelope();
- submissionEnvelope.setUuid(Uuid.newUuid());
- submissionEnvelope.enactStateTransition(SubmissionState.GRAPH_VALID);
- submissionEnvelope = submissionEnvelopeRepository.save(submissionEnvelope);
-
- project = new Project(null);
- project.setSubmissionEnvelope(submissionEnvelope);
- project.getSubmissionEnvelopes().add(submissionEnvelope);
- project = projectRepository.save(project);
-
- process1 = processRepository.save(new Process(null));
- process2 = processRepository.save(new Process(null));
- process3 = processRepository.save(new Process(null));
-
- file = new File(null, "fileName");
- file.setSubmissionEnvelope(submissionEnvelope);
- file = fileRepository.save(file);
-
- uriBuilder = ServletUriComponentsBuilder.fromCurrentContextPath();
- }
-
- @AfterEach
- void tearDown() {
- processRepository.deleteAll();
- fileRepository.deleteAll();
- submissionEnvelopeRepository.deleteAll();
- }
-
- @Test
- public void newFileInSubmissionLinksToSubmissionAndProject() throws Exception {
- //given
- fileRepository.deleteAll();
-
- // when
- webApp.perform(
- post("/submissionEnvelopes/{id}/files", submissionEnvelope.getId())
- .contentType(MediaType.APPLICATION_JSON)
- .content("{\"content\": {}}")
- ).andExpect(status().isAccepted());
-
- //then
- assertThat(fileRepository.findAll()).hasSize(1);
- assertThat(fileRepository.findAllBySubmissionEnvelope(submissionEnvelope)).hasSize(1);
- assertThat(fileRepository.findByProject(project)).hasSize(1);
-
- var newFile = fileRepository.findAll().get(0);
- assertThat(newFile.getSubmissionEnvelope().getId()).isEqualTo(submissionEnvelope.getId());
- assertThat(newFile.getProject().getId()).isEqualTo(project.getId());
- }
-
- @Test
- public void newFileInSubmissionDoesNotFailIfSubmissionHasNoProject() throws Exception {
- //given
- fileRepository.deleteAll();
- projectRepository.deleteAll();
-
- // when
- webApp.perform(
- post("/submissionEnvelopes/{id}/files", submissionEnvelope.getId())
- .contentType(MediaType.APPLICATION_JSON)
- .content("{\"content\": {}}")
- ).andExpect(status().isAccepted());
-
- //then
- assertThat(fileRepository.findAll()).hasSize(1);
- assertThat(fileRepository.findAllBySubmissionEnvelope(submissionEnvelope)).hasSize(1);
-
- var newFile = fileRepository.findAll().get(0);
- assertThat(newFile.getSubmissionEnvelope().getId()).isEqualTo(submissionEnvelope.getId());
- assertThat(newFile.getProject()).isNull();
- }
-
- @Test
- public void testLinkFileAsInputToProcessesUsingPutMethodWithManyProcessesInPayload() throws Exception {
- file.addAsInputToProcess(process1);
- fileRepository.save(file);
-
- webApp.perform(put("/files/{fileId}/inputToProcesses/", file.getId())
- .contentType("text/uri-list")
- .content(uriBuilder.build().toUriString() + "/processes/" + process2.getId() + '\n'
- + uriBuilder.build().toUriString() + "/processes/" + process3.getId()))
- .andExpect(status().isOk());
-
- verifyThatValidationStateChangedToDraftWhenGraphValid(file);
-
- File updatedFile = fileRepository.findById(file.getId()).get();
- assertThat(updatedFile.getInputToProcesses())
- .usingElementComparatorOnFields("id")
- .containsExactly(process2, process3);
- }
-
- @Test
- public void testLinkFileAsInputToMultipleProcessesUsingPostMethodWithManyProcessesInPayload() throws Exception {
- // when
- webApp.perform(post("/files/{fileId}/inputToProcesses/", file.getId())
- .contentType("text/uri-list")
- .content(uriBuilder.build().toUriString() + "/processes/" + process1.getId()
- + '\n' + uriBuilder.build().toUriString() + "/processes/" + process2.getId()))
- .andExpect(status().isOk());
-
- // then
- verifyThatValidationStateChangedToDraftWhenGraphValid(file);
- File updatedFile = fileRepository.findById(file.getId()).get();
- assertThat(updatedFile.getInputToProcesses())
- .usingElementComparatorOnFields("id")
- .containsExactly(process1, process2);
- }
-
- @Test
- public void testLinkFileAsInputToProcessesUsingPostMethodWithOneProcessInPayload() throws Exception {
- // when
- webApp.perform(post("/files/{fileId}/inputToProcesses/", file.getId())
- .contentType("text/uri-list")
- .content(uriBuilder.build().toUriString() + "/processes/" + process1.getId()))
- .andExpect(status().isOk());
-
- // then
- verifyThatValidationStateChangedToDraftWhenGraphValid(file);
- File updatedFile = fileRepository.findById(file.getId()).get();
- assertThat(updatedFile.getInputToProcesses())
- .usingElementComparatorOnFields("id")
- .containsExactly(process1);
- }
-
- @Test
- public void testLinkFileAsDerivedByProcessesUsingPostMethodWithOneProcessInPayload() throws Exception {
- // when
- webApp.perform(post("/files/{fileId}/derivedByProcesses/", file.getId())
- .contentType("text/uri-list")
- .content(uriBuilder.build().toUriString() + "/processes/" + process1.getId()))
- .andExpect(status().isOk());
-
- // then
- verifyThatValidationStateChangedToDraftWhenGraphValid(file);
- File updatedFile = fileRepository.findById(file.getId()).get();
- assertThat(updatedFile.getDerivedByProcesses())
- .usingElementComparatorOnFields("id")
- .contains(process1);
- }
-
- @Test
- public void testLinkFileAsDerivedByProcessesUsingPostMethodWithManyProcessesInPayload() throws Exception {
- // when
- webApp.perform(post("/files/{fileId}/derivedByProcesses/", file.getId())
- .contentType("text/uri-list")
- .content(uriBuilder.build().toUriString() + "/processes/" + process1.getId()
- + '\n' + uriBuilder.build().toUriString() + "/processes/" + process2.getId()))
- .andExpect(status().isOk());
-
- // then
- verifyThatValidationStateChangedToDraftWhenGraphValid(file);
- File updatedFile = fileRepository.findById(file.getId()).get();
- assertThat(updatedFile.getDerivedByProcesses())
- .usingElementComparatorOnFields("id")
- .containsExactly(process1, process2);
- }
-
- @Test
- public void testLinkFileAsDerivedByProcessesUsingPutMethodWithManyProcessesInPayload() throws Exception {
- // given
- file.addAsDerivedByProcess(process1);
- fileRepository.save(file);
-
- // when
- webApp.perform(put("/files/{fileId}/derivedByProcesses/", file.getId())
- .contentType("text/uri-list")
- .content(uriBuilder.build().toUriString() + "/processes/" + process2.getId() + '\n'
- + uriBuilder.build().toUriString() + "/processes/" + process3.getId()))
- .andExpect(status().isOk());
-
- // then
- verifyThatValidationStateChangedToDraftWhenGraphValid(file);
- File updatedFile = fileRepository.findById(file.getId()).get();
- assertThat(updatedFile.getDerivedByProcesses())
- .usingElementComparatorOnFields("id")
- .containsExactly(process2, process3);
- }
-
- @Test
- public void testUnlinkFileAsDerivedByProcesses() throws Exception {
- // given
- file.addAsDerivedByProcess(process1);
- fileRepository.save(file);
-
- // when
- webApp.perform(delete("/files/{fileId}/derivedByProcesses/{processId}", file.getId(), process1.getId()))
- .andExpect(status().isNoContent());
-
- // then
- verifyThatValidationStateChangedToDraftWhenGraphValid(file);
- File updatedFile = fileRepository.findById(file.getId()).get();
- assertThat(updatedFile.getDerivedByProcesses()).doesNotContain(process1);
- }
-
- @Test
- public void testUnlinkFileAsInputToProcesses() throws Exception {
- // given
- file.addAsInputToProcess(process1);
- fileRepository.save(file);
-
- // when
- webApp.perform(delete("/files/{fileId}/inputToProcesses/{processId}", file.getId(), process1.getId()))
- .andExpect(status().isNoContent());
-
- // then
- verifyThatValidationStateChangedToDraftWhenGraphValid(file);
-
- File updatedFile = fileRepository.findById(file.getId()).get();
- assertThat(updatedFile.getInputToProcesses()).doesNotContain(process1);
- }
-
- private void verifyThatValidationStateChangedToDraftWhenGraphValid(MetadataDocument... values) {
- Arrays.stream(values).forEach(value -> {
- verify(validationStateChangeService, times(1)).changeValidationState(value.getType(), value.getId(), ValidationState.DRAFT);
- });
- }
-
- @Test
- public void testValidationJobPatch() throws Exception {
- //given:
- File file = new File(null, "test");
- file.setSubmissionEnvelope(submissionEnvelope);
- file = fileRepository.save(file);
-
- //when:
- String patch = "{ \"validationJob\": { \"validationReport\": { \"validationState\": \"Valid\" }}}";
-
- MvcResult result = webApp
- .perform(patch("/files/{id}", file.getId())
- .contentType(APPLICATION_JSON_VALUE)
- .content(patch))
- .andReturn();
-
- //expect:
- MockHttpServletResponse response = result.getResponse();
- assertThat(response.getContentType()).containsPattern("application/.*json.*");
-
- //and:
- file = fileRepository.findById(file.getId()).get();
- assertThat(file.getValidationJob().getValidationReport().getValidationState()).isEqualTo(ValidationState.VALID);
- }
-
- @Test
- public void when_new_File_ctor__pass() throws Exception {
- String filePayload = objectMapper.writeValueAsString(new File());
- webApp.perform(
- post("/submissionEnvelopes/{id}/files", submissionEnvelope.getId())
- .contentType(MediaType.APPLICATION_JSON)
- .content(filePayload)
- ).andExpect(status().isAccepted());
- }
-
- @Test
- public void when_DataFileUuid_is_null__accepted_with_random() throws Exception {
- ObjectNode patch = createPayloadhNoDataFileUuid();
- webApp.perform(
- post("/submissionEnvelopes/{id}/files", submissionEnvelope.getId())
- .contentType(MediaType.APPLICATION_JSON)
- .content(objectMapper.writeValueAsString(patch))
- ).andExpect(status().isAccepted())
- .andExpect(jsonPath("$.dataFileUuid").isNotEmpty());
- }
-
- @Test
- public void when_payload_is_good__pass() throws Exception {
- ObjectNode patch = createValidFilePayload();
- webApp.perform(
- post("/submissionEnvelopes/{id}/files", submissionEnvelope.getId())
- .contentType(MediaType.APPLICATION_JSON)
- .content(objectMapper.writeValueAsString(patch))
- ).andExpect(status().isAccepted());
- }
-
-
- private ObjectNode createValidFilePayload() {
- ObjectMapper mapper = new ObjectMapper();
- ObjectNode newFilePayload = mapper.createObjectNode();
-
- newFilePayload
- .put("dataFileUuid", UUID.randomUUID().toString())
- .put("fileName", "test-file")
- .put("fileContentType", "text/plain");
- return newFilePayload;
- }
-
- private ObjectNode createPayloadhNoDataFileUuid() {
- ObjectMapper mapper = new ObjectMapper();
- ObjectNode newFilePayload = mapper.createObjectNode();
-
- newFilePayload
- .put("fileName", "test-file")
- .put("fileContentType", "text/plain");
- return newFilePayload;
- }
-}
\ No newline at end of file
diff --git a/src/integration/java/org/humancellatlas/ingest/file/FileServiceTest.java b/src/integration/java/org/humancellatlas/ingest/file/FileServiceTest.java
deleted file mode 100644
index 60f61b319..000000000
--- a/src/integration/java/org/humancellatlas/ingest/file/FileServiceTest.java
+++ /dev/null
@@ -1,169 +0,0 @@
-package org.humancellatlas.ingest.file;
-
-import org.humancellatlas.ingest.biomaterial.BiomaterialRepository;
-import org.humancellatlas.ingest.config.MigrationConfiguration;
-import org.humancellatlas.ingest.core.Checksums;
-import org.humancellatlas.ingest.core.Uuid;
-import org.humancellatlas.ingest.core.exception.CoreEntityNotFoundException;
-import org.humancellatlas.ingest.core.service.MetadataCrudService;
-import org.humancellatlas.ingest.core.service.MetadataUpdateService;
-import org.humancellatlas.ingest.file.web.FileMessage;
-import org.humancellatlas.ingest.process.ProcessRepository;
-import org.humancellatlas.ingest.project.Project;
-import org.humancellatlas.ingest.project.ProjectRepository;
-import org.humancellatlas.ingest.state.MetadataDocumentEventHandler;
-import org.humancellatlas.ingest.state.ValidationState;
-import org.humancellatlas.ingest.submission.SubmissionEnvelope;
-import org.humancellatlas.ingest.submission.SubmissionEnvelopeRepository;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.mockito.Mockito;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.boot.test.mock.mockito.MockBean;
-import org.springframework.context.ApplicationContext;
-import org.springframework.dao.OptimisticLockingFailureException;
-
-import java.util.ArrayList;
-import java.util.UUID;
-import java.util.stream.Stream;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.*;
-
-
-@SpringBootTest
-public class FileServiceTest {
- @MockBean
- MigrationConfiguration migrationConfiguration;
-
- @MockBean
- FileRepository fileRepository;
-
- @MockBean
- SubmissionEnvelopeRepository submissionEnvelopeRepository;
-
- @MockBean
- BiomaterialRepository biomaterialRepository;
-
- @MockBean
- ProcessRepository processRepository;
-
- @MockBean
- ProjectRepository projectRepository;
-
- @MockBean
- MetadataDocumentEventHandler metadataDocumentEventHandler;
-
- @MockBean
- MetadataCrudService metadataCrudService;
-
- @MockBean
- MetadataUpdateService metadataUpdateService;
-
- @Autowired
- FileService fileService;
-
- @Autowired
- private ApplicationContext applicationContext;
-
- FileMessage fileMessage;
-
- SubmissionEnvelope submissionEnvelope;
-
- File file;
-
- Project project;
-
- @BeforeEach
- void setUp() {
- applicationContext.getBeansWithAnnotation(MockBean.class).forEach(Mockito::reset);
-
- Checksums checksums = new Checksums("sha1", "sha256", "crc32c", "s3Etag");
- String submissionUuid = UUID.randomUUID().toString();
- String filename = "filename";
- fileMessage = new FileMessage("cloudUrl", filename, submissionUuid, "content_type", checksums, 123);
-
- submissionEnvelope = new SubmissionEnvelope();
-
- project = spy(new Project(null));
- when(project.getId()).thenReturn("projectId");
-
- file = new File(null, filename);
- var files = new ArrayList();
- files.add(file);
-
- when(submissionEnvelopeRepository.findByUuid(any(Uuid.class))).thenReturn(submissionEnvelope);
- when(projectRepository.findBySubmissionEnvelopesContains(submissionEnvelope)).thenReturn(Stream.of(project));
- when(fileRepository.findBySubmissionEnvelopeAndFileName(submissionEnvelope, fileMessage.getFileName())).thenReturn(files);
- when(fileRepository.save(file)).thenReturn(file);
- }
-
- @Test
- public void testCreateFileFromFileMessage() throws CoreEntityNotFoundException {
- //given:
- when(fileRepository.findBySubmissionEnvelopeAndFileName(submissionEnvelope, fileMessage.getFileName())).thenReturn(new ArrayList<>());
-
- //when:
- fileService.createFileFromFileMessage(fileMessage);
-
- //then:
- verify(metadataCrudService).addToSubmissionEnvelopeAndSave(any(File.class), any(SubmissionEnvelope.class));
- }
-
- @Test
- public void testCreateFileFromFileMessageNotCreated() throws CoreEntityNotFoundException {
- //when:
- fileService.createFileFromFileMessage(fileMessage);
-
- //then:
- verify(metadataCrudService, never()).addToSubmissionEnvelopeAndSave(any(File.class), any(SubmissionEnvelope.class));
- }
-
-
- @Test
- public void testUpdateFileFromFileMessage() throws CoreEntityNotFoundException {
- //when:
- fileService.updateFileFromFileMessage(fileMessage);
-
- //then:
- verify(fileRepository).save(file);
- assertThat(file.getCloudUrl()).isEqualTo(fileMessage.getCloudUrl());
- assertThat(file.getChecksums()).isEqualTo(fileMessage.getChecksums());
- assertThat(file.getFileContentType()).isEqualTo(fileMessage.getContentType());
- assertThat(file.getValidationState()).isEqualTo(ValidationState.DRAFT);
- }
-
- @Test
- public void testUpdateFileFromFileMessageRetry() throws CoreEntityNotFoundException {
- //given:
- when(fileRepository.save(file))
- .thenThrow(new OptimisticLockingFailureException("Error"))
- .thenReturn(file);
-
- //when:
- fileService.updateFileFromFileMessage(fileMessage);
-
- //then:
- verify(fileRepository, times(2)).save(file);
- }
-
- @Test
- public void testUpdateFileFromFileMessageMaxRetries() throws CoreEntityNotFoundException {
- //given:
- when(fileRepository.save(file))
- .thenThrow(new OptimisticLockingFailureException("Error"));
-
- //when:
- assertThatExceptionOfType(OptimisticLockingFailureException.class).isThrownBy(() -> {
- fileService.updateFileFromFileMessage(fileMessage);
- });
-
- //then:
- verify(fileRepository, times(5)).save(file);
- }
-
-}
-
diff --git a/src/integration/java/org/humancellatlas/ingest/process/ProcessControllerTest.java b/src/integration/java/org/humancellatlas/ingest/process/ProcessControllerTest.java
deleted file mode 100644
index 8aaacbc98..000000000
--- a/src/integration/java/org/humancellatlas/ingest/process/ProcessControllerTest.java
+++ /dev/null
@@ -1,254 +0,0 @@
-package org.humancellatlas.ingest.process;
-
-import org.humancellatlas.ingest.config.MigrationConfiguration;
-import org.humancellatlas.ingest.core.MetadataDocument;
-import org.humancellatlas.ingest.core.Uuid;
-import org.humancellatlas.ingest.core.service.ValidationStateChangeService;
-import org.humancellatlas.ingest.messaging.MessageRouter;
-import org.humancellatlas.ingest.project.Project;
-import org.humancellatlas.ingest.project.ProjectRepository;
-import org.humancellatlas.ingest.protocol.Protocol;
-import org.humancellatlas.ingest.protocol.ProtocolRepository;
-import org.humancellatlas.ingest.state.SubmissionState;
-import org.humancellatlas.ingest.state.ValidationState;
-import org.humancellatlas.ingest.submission.SubmissionEnvelope;
-import org.humancellatlas.ingest.submission.SubmissionEnvelopeRepository;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.autoconfigure.data.mongo.AutoConfigureDataMongo;
-import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.boot.test.mock.mockito.MockBean;
-import org.springframework.http.MediaType;
-import org.springframework.test.web.servlet.MockMvc;
-import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
-import org.springframework.web.util.UriComponentsBuilder;
-
-import java.util.Arrays;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
-
-@SpringBootTest
-@AutoConfigureDataMongo()
-@AutoConfigureMockMvc(printOnlyOnFailure = false)
-class ProcessControllerTest {
- @MockBean
- ValidationStateChangeService validationStateChangeService;
-
- @MockBean
- private MessageRouter messageRouter;
-
- @MockBean
- private MigrationConfiguration migrationConfiguration;
-
- @Autowired
- private MockMvc webApp;
-
- @Autowired
- private ProcessRepository processRepository;
-
- @Autowired
- private ProtocolRepository protocolRepository;
-
- @Autowired
- private ProjectRepository projectRepository;
-
- @Autowired
- private SubmissionEnvelopeRepository submissionEnvelopeRepository;
-
- Protocol protocol1;
-
- Protocol protocol2;
-
- Protocol protocol3;
-
- Project project;
-
- Process process;
-
- UriComponentsBuilder uriBuilder;
-
- SubmissionEnvelope submissionEnvelope;
-
- @BeforeEach
- void setUp() {
- submissionEnvelope = new SubmissionEnvelope();
- submissionEnvelope.setUuid(Uuid.newUuid());
- submissionEnvelope.enactStateTransition(SubmissionState.GRAPH_VALID);
- submissionEnvelope = submissionEnvelopeRepository.save(submissionEnvelope);
-
- protocol1 = protocolRepository.save(new Protocol(null));
- protocol2 = protocolRepository.save(new Protocol(null));
- protocol3 = protocolRepository.save(new Protocol(null));
-
- project = new Project(null);
- project.setSubmissionEnvelope(submissionEnvelope);
- project.getSubmissionEnvelopes().add(submissionEnvelope);
- project = projectRepository.save(project);
-
- process = new Process(null);
- process.setSubmissionEnvelope(submissionEnvelope);
- process = processRepository.save(process);
-
- uriBuilder = ServletUriComponentsBuilder.fromCurrentContextPath();
- }
-
- @AfterEach
- void tearDown() {
- submissionEnvelopeRepository.deleteAll();
- processRepository.deleteAll();
- protocolRepository.deleteAll();
- projectRepository.deleteAll();
- }
-
- @Test
- public void newProcessInSubmissionLinksToSubmissionAndProject() throws Exception {
- //given
- processRepository.deleteAll();
-
- // when
- webApp.perform(
- post("/submissionEnvelopes/{id}/processes", submissionEnvelope.getId())
- .contentType(MediaType.APPLICATION_JSON)
- .content("{\"content\": {}}")
- ).andExpect(status().isAccepted());
-
- //then
- assertThat(processRepository.findAll()).hasSize(1);
- assertThat(processRepository.findAllBySubmissionEnvelope(submissionEnvelope)).hasSize(1);
- assertThat(processRepository.findByProject(project)).hasSize(1);
-
- var newProcess = processRepository.findAll().get(0);
- assertThat(newProcess.getSubmissionEnvelope().getId()).isEqualTo(submissionEnvelope.getId());
- assertThat(newProcess.getProject().getId()).isEqualTo(project.getId());
- assertThat(newProcess.getProjects()).hasSize(1);
- assertThat(newProcess.getProjects().stream().findFirst().get().getId()).isEqualTo(project.getId());
- }
-
- @Test
- public void newProcessInSubmissionDoesNotFailIfSubmissionHasNoProject() throws Exception {
- //given
- processRepository.deleteAll();
- projectRepository.deleteAll();
-
- // when
- webApp.perform(
- post("/submissionEnvelopes/{id}/processes", submissionEnvelope.getId())
- .contentType(MediaType.APPLICATION_JSON)
- .content("{\"content\": {}}")
- ).andExpect(status().isAccepted());
-
- //then
- assertThat(processRepository.findAll()).hasSize(1);
- assertThat(processRepository.findAllBySubmissionEnvelope(submissionEnvelope)).hasSize(1);
-
- var newProcess = processRepository.findAll().get(0);
- assertThat(newProcess.getSubmissionEnvelope().getId()).isEqualTo(submissionEnvelope.getId());
- assertThat(newProcess.getProject()).isNull();
- assertThat(newProcess.getProjects()).isEmpty();
- }
-
- @Test
- public void testLinkProtocolsToProcessUsingPutMethodWithManyProtocolsInPayload() throws Exception {
- // given
- process.addProtocol(protocol1);
- processRepository.save(process);
-
- // when
- webApp.perform(put("/processes/{id}/protocols/", process.getId())
- .contentType("text/uri-list")
- .content(uriBuilder.build().toUriString() + "/protocols/" + protocol2.getId()
- + '\n' + uriBuilder.build().toUriString() + "/protocols/" + protocol3.getId()))
- .andExpect(status().isOk());
-
- // then
- verifyThatValidationStateChangedToDraftWhenGraphValid(process);
- Process updatedProcess = processRepository.findById(process.getId()).get();
- assertThat(updatedProcess.getProtocols())
- .usingElementComparatorOnFields("id")
- .containsExactly(protocol2, protocol3);
- }
-
- @Test
- public void testLinkProtocolsToProcessUsingPostMethodWithManyProtocolsInPayload() throws Exception {
- // when
- webApp.perform(post("/processes/{id}/protocols/", process.getId())
- .contentType("text/uri-list")
- .content(uriBuilder.build().toUriString() + "/protocols/" + protocol1.getId()
- + '\n' + uriBuilder.build().toUriString() + "/protocols/" + protocol2.getId()))
- .andExpect(status().isOk());
-
- // then
- verifyThatValidationStateChangedToDraftWhenGraphValid(process);
- Process updatedProcess = processRepository.findById(process.getId()).get();
- assertThat(updatedProcess.getProtocols())
- .usingElementComparatorOnFields("id")
- .containsExactly(protocol1, protocol2);
- }
-
- @Test
- public void testLinkProtocolsToProcessUsingPostMethodWithOneProtocolInPayload() throws Exception {
- // when
- webApp.perform(post("/processes/{processId}/protocols/", process.getId())
- .contentType("text/uri-list")
- .content(uriBuilder.build().toUriString() + "/protocols/" + protocol1.getId()))
- .andExpect(status().isOk());
-
- // then
- verifyThatValidationStateChangedToDraftWhenGraphValid(process);
- Process updatedProcess = processRepository.findById(process.getId()).get();
- assertThat(updatedProcess.getProtocols())
- .usingElementComparatorOnFields("id")
- .containsExactly(protocol1);
- }
-
- @Test
- public void testUnlinkProtocolFromProcess() throws Exception {
- // given
- process.addProtocol(protocol1);
- processRepository.save(process);
-
- // when
- webApp.perform(delete("/processes/{processId}/protocols/{protocolId}", process.getId(), protocol1.getId()))
- .andExpect(status().isNoContent());
-
- // then
- verifyThatValidationStateChangedToDraftWhenGraphValid(process);
-
- Process updatedProcess = processRepository.findById(process.getId()).get();
- assertThat(updatedProcess.getProtocols()).doesNotContain(protocol1);
- }
-
- @Test
- public void testLinkProjectToProcessDoesNotChangeTheirValidationStatesToDraft() throws Exception {
- webApp.perform(put("/processes/{processId}/project", process.getId())
- .contentType("text/uri-list")
- .content(uriBuilder.build().toUriString() + "/projects/" + project.getId()))
- .andExpect(status().isNoContent());
-
- verify(validationStateChangeService, times(0)).changeValidationState(any(), any(), eq(ValidationState.DRAFT));
- }
-
- @Test
- public void testUnlinkProjectFromProcessDoesNotChangeTheirValidationStatesToDraft() throws Exception {
- webApp.perform(delete("/processes/{processId}/project/{projectId}", process.getId(), project.getId()))
- .andExpect(status().isNoContent());
-
- verify(validationStateChangeService, times(0)).changeValidationState(any(), any(), eq(ValidationState.DRAFT));
- }
-
- private void verifyThatValidationStateChangedToDraftWhenGraphValid(MetadataDocument... values) {
- Arrays.stream(values).forEach(
- value -> verify(validationStateChangeService, times(1))
- .changeValidationState(value.getType(), value.getId(), ValidationState.DRAFT)
- );
- }
-}
\ No newline at end of file
diff --git a/src/integration/java/org/humancellatlas/ingest/process/ProcessRepositoryTest.java b/src/integration/java/org/humancellatlas/ingest/process/ProcessRepositoryTest.java
deleted file mode 100644
index 065a656e9..000000000
--- a/src/integration/java/org/humancellatlas/ingest/process/ProcessRepositoryTest.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package org.humancellatlas.ingest.process;
-
-import org.humancellatlas.ingest.config.MigrationConfiguration;
-import org.humancellatlas.ingest.messaging.MessageRouter;
-import org.humancellatlas.ingest.protocol.Protocol;
-import org.humancellatlas.ingest.protocol.ProtocolRepository;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.Test;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest;
-import org.springframework.boot.test.mock.mockito.MockBean;
-
-import java.util.Optional;
-
-import static java.util.Arrays.asList;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assumptions.assumeThat;
-
-@DataMongoTest
-public class ProcessRepositoryTest {
-
- @Autowired
- private ProcessRepository processRepository;
-
- @Autowired
- private ProtocolRepository protocolRepository;
-
- @MockBean
- private MigrationConfiguration migrationConfiguration;
-
- @MockBean
- private MessageRouter messageRouter;
-
- @AfterEach
- private void tearDown() {
- processRepository.deleteAll();
- protocolRepository.deleteAll();
- }
-
- @Test
- public void findFirstByProtocolNonUnique() {
- //given:
- Protocol protocol = protocolRepository.save(new Protocol(null));
-
- Process process1 = new Process(null);
- process1.addProtocol(protocol);
- process1 = processRepository.save(process1);
-
- Process process2 = new Process(null);
- process2.addProtocol(protocol);
- process2 = processRepository.save(process2);
-
- //and:
- assumeThat(processRepository.findAll()).hasSize(2);
-
- //when:
- Optional first = processRepository.findFirstByProtocolsContains(protocol);
-
- // then
- assertThat(first.isPresent()).isTrue();
- assertThat(first.get().getId()).isIn(asList(process1.getId(), process2.getId()));
- }
-}
diff --git a/src/integration/java/org/humancellatlas/ingest/project/ProjectFilterTest.java b/src/integration/java/org/humancellatlas/ingest/project/ProjectFilterTest.java
deleted file mode 100644
index ccefc29be..000000000
--- a/src/integration/java/org/humancellatlas/ingest/project/ProjectFilterTest.java
+++ /dev/null
@@ -1,534 +0,0 @@
-package org.humancellatlas.ingest.project;
-
-import org.humancellatlas.ingest.audit.AuditEntryService;
-import org.humancellatlas.ingest.bundle.BundleManifestRepository;
-import org.humancellatlas.ingest.core.Uuid;
-import org.humancellatlas.ingest.core.service.MetadataCrudService;
-import org.humancellatlas.ingest.core.service.MetadataUpdateService;
-import org.humancellatlas.ingest.project.web.SearchFilter;
-import org.humancellatlas.ingest.project.web.SearchType;
-import org.humancellatlas.ingest.schemas.SchemaService;
-import org.humancellatlas.ingest.submission.SubmissionEnvelopeRepository;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest;
-import org.springframework.boot.test.mock.mockito.MockBean;
-import org.springframework.data.domain.Page;
-import org.springframework.data.domain.PageRequest;
-import org.springframework.data.domain.Pageable;
-import org.springframework.data.mongodb.core.MongoTemplate;
-import org.springframework.data.mongodb.core.index.TextIndexDefinition;
-import org.springframework.data.mongodb.core.query.Criteria;
-import org.springframework.data.mongodb.core.query.Query;
-
-import java.time.Instant;
-import java.time.temporal.ChronoUnit;
-import java.util.Arrays;
-import java.util.Comparator;
-import java.util.List;
-import java.util.Map;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-@DataMongoTest
-class ProjectFilterTest {
-
- // class under test
- private ProjectService projectService;
-
- // participants
- @Autowired
- private MongoTemplate mongoTemplate;
-
- @MockBean
- private SubmissionEnvelopeRepository submissionEnvelopeRepository;
-
- @MockBean
- private ProjectRepository projectRepository;
-
- @MockBean
- private MetadataCrudService metadataCrudService;
-
- @MockBean
- private MetadataUpdateService metadataUpdateService;
-
- @MockBean
- private SchemaService schemaService;
-
- @MockBean
- private BundleManifestRepository bundleManifestRepository;
-
- @MockBean
- private ProjectEventHandler projectEventHandler;
-
- @MockBean
- private AuditEntryService auditEntryService;
-
- private Project project1;
- private Project project2;
- private Project project3;
-
- Comparator upToMillies = Comparator.comparing(d -> d.truncatedTo(ChronoUnit.MILLIS));
-
- @Test
- void test_raw_criteria() {
- Query query = new Query().addCriteria(Criteria.where("content.project_core.project_title").regex("project1", "i"));
- Project actual = this.mongoTemplate.findOne(query, Project.class);
- assertThat(actual)
- .usingComparatorForFields(upToMillies, "contentLastModified")
- .isEqualToComparingFieldByFieldRecursively(project1);
-
- }
-
- @Test
- void test_criteria_building() {
- SearchFilter searchFilter = SearchFilter.builder().wranglingState("NEW").build();
- Query query = ProjectQueryBuilder.buildProjectsQuery(searchFilter);
- Project actual = this.mongoTemplate.find(query, Project.class).get(0);
- assertThat(actual)
- .usingComparatorForFields(upToMillies, "contentLastModified")
- .isEqualToComparingFieldByFieldRecursively(project1);
- }
-
- @Test
- void test_criteria_building_with_pageable() {
- SearchFilter searchFilter = SearchFilter.builder().search("project1").build();
- Query query = ProjectQueryBuilder.buildProjectsQuery(searchFilter);
- Pageable pageable = PageRequest.of(0, 10);
- Project actual = this.mongoTemplate.find(query.with(pageable), Project.class).get(0);
- assertThat(actual)
- .usingComparatorForFields(upToMillies, "contentLastModified")
- .isEqualToComparingFieldByFieldRecursively(project1);
- }
-
- @Test
- void filter_by_state() {
- Project project4 = makeProject("project4");
- project4.setWranglingState(WranglingState.IN_PROGRESS);
- this.mongoTemplate.save(project4);
-
- //when
- SearchFilter filterNew = SearchFilter.builder().wranglingState("NEW").build();
-
- Pageable pageable = PageRequest.of(0, 10);
- Page result = projectService.filterProjects(filterNew, pageable);
-
- // then
- assertThat(result.getContent())
- .hasSize(3)
- .usingComparatorForElementFieldsWithType(upToMillies, Instant.class)
- .usingRecursiveFieldByFieldElementComparator()
- .containsExactlyInAnyOrder(project1, project2, project3);
- }
-
- @Test
- void filter_by_wrangler() {
- // given
- //when
- SearchFilter searchFilter = SearchFilter.builder().primaryWrangler(this.project2.getPrimaryWrangler()).build();
-
- Pageable pageable = PageRequest.of(0, 10);
- Page result = projectService.filterProjects(searchFilter, pageable);
-
- // then
- assertThat(result.getTotalElements()).isEqualTo(1);
- assertThat(result.getContent())
- .hasSize(1)
- .usingComparatorForElementFieldsWithType(upToMillies, Instant.class)
- .usingRecursiveFieldByFieldElementComparator()
- .containsExactly(this.project2);
- }
-
- @Test
- void filter_by_wrangling_priority() {
- //given
- Project project4 = makeProject("project4");
- project4.setWranglingPriority(3);
- this.mongoTemplate.save(project4);
- //when
- SearchFilter searchFilter = SearchFilter.builder().wranglingPriority(this.project1.getWranglingPriority()).build();
-
- Pageable pageable = PageRequest.of(0, 10);
- Page result = projectService.filterProjects(searchFilter, pageable);
-
- // then
- assertThat(result.getTotalElements()).isEqualTo(3);
- assertThat(result.getContent())
- .hasSize(3)
- .usingComparatorForElementFieldsWithType(upToMillies, Instant.class)
- .usingRecursiveFieldByFieldElementComparator()
- .containsExactlyInAnyOrder(project1, project2, project3);
- }
-
- @Test
- void filter_by_official_hca_publication() {
- //given
- Project project4 = makeProject("project4");
- var content = Map.of(
- "project_core", Map.of("project_title", "Project 4"),
- "publications", List.of(Map.of("official_hca_publication", true))
- );
- project4.setContent(content);
- this.mongoTemplate.save(project4);
-
- //when
- SearchFilter searchFilter = SearchFilter.builder().hasOfficialHcaPublication(true).build();
-
- Pageable pageable = PageRequest.of(0, 10);
- Page result = projectService.filterProjects(searchFilter, pageable);
-
- // then
- assertThat(result.getTotalElements()).isEqualTo(1);
- assertThat(result.getContent())
- .hasSize(1)
- .usingComparatorForElementFieldsWithType(upToMillies, Instant.class)
- .usingRecursiveFieldByFieldElementComparator()
- .containsExactly(project4);
- }
-
- @Test
- void filter_by_identifying_organisms() {
- //given
- Project project4 = makeProject("project4");
- String human = "Human";
- project4.setIdentifyingOrganisms(List.of(human));
- this.mongoTemplate.save(project4);
-
- //when
- SearchFilter searchFilter = SearchFilter.builder().identifyingOrganism(human).build();
-
- Pageable pageable = PageRequest.of(0, 10);
- Page result = projectService.filterProjects(searchFilter, pageable);
-
- // then
- assertThat(result.getTotalElements()).isEqualTo(1);
- assertThat(result.getContent())
- .hasSize(1)
- .usingComparatorForElementFieldsWithType(upToMillies, Instant.class)
- .usingRecursiveFieldByFieldElementComparator()
- .containsExactly(project4);
- }
-
- @Test
- void filter_by_organ_ontology() {
- //given
- Project project4 = makeProject("project4");
- String ontologyTerm = "AN_ONTOLOGY";
- project4.setOrgan(Map.of("ontologies", List.of(Map.of("ontology", ontologyTerm))));
- this.mongoTemplate.save(project4);
- //when
- SearchFilter searchFilter = SearchFilter.builder().organOntology(ontologyTerm).build();
-
- Pageable pageable = PageRequest.of(0, 10);
- Page result = projectService.filterProjects(searchFilter, pageable);
-
- // then
- assertThat(result.getTotalElements()).isEqualTo(1);
- assertThat(result.getContent())
- .hasSize(1)
- .usingComparatorForElementFieldsWithType(upToMillies, Instant.class)
- .usingRecursiveFieldByFieldElementComparator()
- .containsExactly(project4);
- }
-
- @Test
- void filter_by_cell_count() {
- //given
- Project project4 = makeProject("project4");
- project4.setCellCount(1000);
- this.mongoTemplate.save(project4);
- //when
- SearchFilter searchFilter = SearchFilter.builder().maxCellCount(project1.getCellCount()).minCellCount(0).build();
-
- Pageable pageable = PageRequest.of(0, 10);
- Page result = projectService.filterProjects(searchFilter, pageable);
-
- // then
- assertThat(result.getTotalElements()).isEqualTo(3);
- assertThat(result.getContent())
- .hasSize(3)
- .usingComparatorForElementFieldsWithType(upToMillies, Instant.class)
- .usingRecursiveFieldByFieldElementComparator()
- .containsExactlyInAnyOrder(project1, project2, project3);
- }
-
- @Test
- void filter_by_data_access() {
- //given
- Project project4 = makeProject("project4");
- project4.setDataAccess(Map.of("type", DataAccessTypes.OPEN.getLabel()));
- this.mongoTemplate.save(project4);
- //when
- SearchFilter searchFilter = SearchFilter.builder().dataAccess(DataAccessTypes.OPEN).build();
-
- Pageable pageable = PageRequest.of(0, 10);
- Page result = projectService.filterProjects(searchFilter, pageable);
-
- // then
- assertThat(result.getTotalElements()).isEqualTo(1);
- assertThat(result.getContent())
- .hasSize(1)
- .usingComparatorForElementFieldsWithType(upToMillies, Instant.class)
- .usingRecursiveFieldByFieldElementComparator()
- .containsExactly(project4);
- }
-
- @Test
- void filter_by_text() {
- // given
- //when
- SearchFilter searchFilter = SearchFilter.builder().search("project1").build();
-
- Pageable pageable = PageRequest.of(0, 10);
- Page result = projectService.filterProjects(searchFilter, pageable);
-
- // then
- assertThat(result.getContent())
- .hasSize(1)
- .usingComparatorForElementFieldsWithType(upToMillies, Instant.class)
- .usingElementComparatorIgnoringFields("supplementaryFiles", "submissionEnvelopes")
- .containsExactly(project1);
- }
-
- @Test
- void query_all_keywords(){
- SearchFilter searchFilter = SearchFilter.builder().search("human liver").build();
-
- Pageable pageable = PageRequest.of(0, 10);
- Page result = projectService.filterProjects(searchFilter, pageable);
-
- // then
- assertThat(result.getContent())
- .hasSize(1)
- .usingComparatorForElementFieldsWithType(upToMillies, Instant.class)
- .usingElementComparatorIgnoringFields("supplementaryFiles", "submissionEnvelopes")
- .containsExactly(project1);
- }
- @Test
- void query_all_keywords__order_independent(){
- SearchFilter searchFilter = SearchFilter.builder()
- .search("liver human")
- .searchType(SearchType.AllKeywords)
- .build();
-
- Pageable pageable = PageRequest.of(0, 10);
- Page result = projectService.filterProjects(searchFilter, pageable);
-
- // then
- assertThat(result.getContent())
- .hasSize(1)
- .usingComparatorForElementFieldsWithType(upToMillies, Instant.class)
- .usingElementComparatorIgnoringFields("supplementaryFiles", "submissionEnvelopes")
- .containsExactly(project1);
- }
- @Test
- void query_any_keywords(){
- SearchFilter searchFilter = SearchFilter.builder()
- .search("liver mouse")
- .searchType(SearchType.AnyKeyword)
- .build();
-
- Pageable pageable = PageRequest.of(0, 10);
- Page result = projectService.filterProjects(searchFilter, pageable);
- Page resultFromReverse = projectService.filterProjects(searchFilter, pageable);
-
- // then
- assertThat(result.getContent())
- .hasSize(2)
- .usingComparatorForElementFieldsWithType(upToMillies, Instant.class)
- .usingElementComparatorIgnoringFields("supplementaryFiles", "submissionEnvelopes")
- .containsExactlyInAnyOrder(project1, project2);
- }
- @Test
- void query_exact_phrase__correct_order(){
- SearchFilter searchFilter = SearchFilter.builder()
- .search("human liver")
- .searchType(SearchType.ExactMatch)
- .build();
-
- Pageable pageable = PageRequest.of(0, 10);
- Page result = projectService.filterProjects(searchFilter, pageable);
- Page resultFromReverse = projectService.filterProjects(searchFilter, pageable);
-
- // then
- assertThat(result.getContent())
- .hasSize(1)
- .usingComparatorForElementFieldsWithType(upToMillies, Instant.class)
- .usingElementComparatorIgnoringFields("supplementaryFiles", "submissionEnvelopes")
- .containsExactly(project1);
- }
-
- @Test
- void query_exact_phrase__reverse_order(){
- SearchFilter searchFilter = SearchFilter.builder()
- .search("liver human")
- .searchType(SearchType.ExactMatch)
- .build();
-
- Pageable pageable = PageRequest.of(0, 10);
- Page result = projectService.filterProjects(searchFilter, pageable);
-
- // then
- assertThat(result.getContent())
- .hasSize(0);
- }
-
- @Test
- void lookup_by_uuid() {
- String uuidString = project1.getUuid().getUuid().toString();
- SearchFilter searchFilter = SearchFilter.builder()
- .search(uuidString)
- .build();
-
- Pageable pageable = PageRequest.of(0, 10);
- Page result = projectService.filterProjects(searchFilter, pageable);
-
- // then
- assertThat(result.getContent())
- .hasSize(1)
- .usingComparatorForElementFieldsWithType(upToMillies, Instant.class)
- .usingElementComparatorIgnoringFields("supplementaryFiles", "submissionEnvelopes")
- .containsExactly(project1);
- }
-
- @Test
- void filter_by_release() {
- //given
- Project project4 = makeProject("project4");
- project4.setDcpReleaseNumber(11);
- this.mongoTemplate.save(project4);
- //when
- SearchFilter searchFilter = SearchFilter.builder().dcpReleaseNumber(11).build();
-
- Pageable pageable = PageRequest.of(0, 10);
- Page result = projectService.filterProjects(searchFilter, pageable);
-
- // then
- assertThat(result.getTotalElements()).isEqualTo(1);
- assertThat(result.getContent())
- .hasSize(1)
- .usingComparatorForElementFieldsWithType(upToMillies, Instant.class)
- .usingRecursiveFieldByFieldElementComparator()
- .containsExactlyInAnyOrder(project4);
- }
-
- @Test
- void filter_by_project_labels() {
- //given
- Project project4 = makeProject("project4");
- project4.setProjectLabels(List.of("CellxGene"));
- this.mongoTemplate.save(project4);
- //when
- SearchFilter searchFilter = SearchFilter.builder().projectLabels("CellxGene").build();
-
- Pageable pageable = PageRequest.of(0, 10);
- Page result = projectService.filterProjects(searchFilter, pageable);
-
- // then
- assertThat(result.getTotalElements()).isEqualTo(1);
- assertThat(result.getContent())
- .hasSize(1)
- .usingComparatorForElementFieldsWithType(upToMillies, Instant.class)
- .usingRecursiveFieldByFieldElementComparator()
- .containsExactlyInAnyOrder(project4);
- }
-
- @Test
- void filter_by_project_networks() {
- //given
- Project project5 = makeProject("project5");
- project5.setProjectNetworks(List.of("Lung"));
- this.mongoTemplate.save(project5);
- //when
- SearchFilter searchFilter = SearchFilter.builder().projectNetworks("Lung").build();
-
- Pageable pageable = PageRequest.of(0, 10);
- Page result = projectService.filterProjects(searchFilter, pageable);
-
- // then
- assertThat(result.getTotalElements()).isEqualTo(1);
- assertThat(result.getContent())
- .hasSize(1)
- .usingComparatorForElementFieldsWithType(upToMillies, Instant.class)
- .usingRecursiveFieldByFieldElementComparator()
- .containsExactlyInAnyOrder(project5);
- }
-
- @Test
- void all_args_constructor() {
- new SearchFilter(
- "a",
- "b",
- "c",
- 1,
- false,
- "Human",
- "AN_ONTOLOGY_TERM",
- 0,
- 10000,
- 1,
- DataAccessTypes.MANAGED,
- "a label",
- "a network",
- false,
- SearchType.AllKeywords
- );
- }
-
- private static Project makeProject(String title) {
- Map projectJson = ProjectJson.fromTitle(title).toMap();
- Project project = new Project(projectJson.get("content"));
- project.setIsUpdate(false);
- project.setPrimaryWrangler("wrangler_" + title);
- project.setWranglingState(WranglingState.NEW);
- project.setUuid(Uuid.newUuid());
- project.setCellCount(100);
- project.setWranglingPriority(1);
- project.setDcpReleaseNumber(1);
- return project;
- }
-
- @BeforeEach
- private void setup() {
- initProjectService();
- initTestData();
- }
-
- private void initTestData() {
- this.project1 = makeProject("project1 human liver");
- this.project2 = makeProject("project2 mouse liver");
- this.project3 = makeProject("project3 lung human");
- Arrays.asList(project1, project2, project3).forEach(project -> {
- this.mongoTemplate.save(project);
- this.projectService.register(project);
- });
- this.mongoTemplate.indexOps(Project.class).ensureIndex(
- new TextIndexDefinition.TextIndexDefinitionBuilder()
- .onField("content.project_core.project_title")
- .build()
- );
- assertThat(this.mongoTemplate.findAll(Project.class)).hasSize(3);
- }
-
- private void initProjectService() {
- this.projectService = new ProjectService(
- mongoTemplate,
- submissionEnvelopeRepository,
- projectRepository,
- metadataCrudService,
- metadataUpdateService,
- schemaService,
- bundleManifestRepository,
- auditEntryService,
- projectEventHandler
- );
- assertThat(this.mongoTemplate.findAll(Project.class)).hasSize(0);
- }
-
- @AfterEach
- private void tearDown() {
- this.mongoTemplate.dropCollection(Project.class);
- }
-}
diff --git a/src/integration/java/org/humancellatlas/ingest/project/ProjectJson.java b/src/integration/java/org/humancellatlas/ingest/project/ProjectJson.java
deleted file mode 100644
index 0b017b694..000000000
--- a/src/integration/java/org/humancellatlas/ingest/project/ProjectJson.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package org.humancellatlas.ingest.project;
-
-import com.fasterxml.jackson.core.type.TypeReference;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-
-import java.util.Map;
-
-public class ProjectJson {
- String title;
-
- public static ProjectJson fromTitle(String title){
- ProjectJson project = new ProjectJson();
- project.title = title;
- return project;
- }
-
- public ObjectNode toObjectNode() {
- ObjectMapper mapper = new ObjectMapper();
- ObjectNode content = mapper.createObjectNode();
- ObjectNode projectCore0 = content.putObject("project_core");
- projectCore0.put("project_title", this.title);
-
- ObjectNode metadata = mapper.createObjectNode();
- metadata.set("content", content);
-
- return metadata;
- }
-
- public Map toMap() {
- ObjectMapper mapper = new ObjectMapper();
- ObjectNode project = this.toObjectNode();
- return mapper.convertValue(project, new TypeReference