Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AJ-1188 Add wds consumer tests against datarepo provider #378

Merged
merged 33 commits into from
Nov 9, 2023
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
857299b
first outline
calypsomatic Oct 13, 2023
5573152
aha
calypsomatic Oct 13, 2023
4ac9d91
flesh out more pacts
calypsomatic Oct 16, 2023
f3c2877
try different body
calypsomatic Oct 18, 2023
d10f632
try plain path
calypsomatic Oct 19, 2023
d3d5a3d
test
calypsomatic Oct 20, 2023
05e2f8b
no variables in path anywhere
calypsomatic Oct 20, 2023
fe8555f
Merge branch 'main' into aj-1188-tdr-consumer
calypsomatic Oct 20, 2023
8cd4401
Update publish-pacts.yml
calypsomatic Oct 24, 2023
e8895d8
Update publish-pacts.yml
calypsomatic Oct 24, 2023
03f7302
rename tdr-provider
calypsomatic Oct 24, 2023
11b95a5
Update publish-pacts.yml
calypsomatic Oct 24, 2023
47e51fd
rename pacticipants
calypsomatic Oct 26, 2023
9a916c3
Update publish-pacts.yml
calypsomatic Oct 26, 2023
73575cf
Merge branch 'main' into aj-1188-tdr-consumer
calypsomatic Oct 26, 2023
61b117d
re-rename consumer
calypsomatic Oct 30, 2023
f095429
Update publish-pacts.yml
calypsomatic Nov 1, 2023
d63d575
remove unnecessary body expectation
calypsomatic Nov 1, 2023
41c5e3e
Update publish-pacts.yml
calypsomatic Nov 1, 2023
5b536d1
small pr comment improvements
calypsomatic Nov 2, 2023
b071e41
Merge branch 'main' into aj-1188-tdr-consumer
calypsomatic Nov 2, 2023
5bd6837
Update service/src/test/java/org/databiosphere/workspacedataservice/p…
calypsomatic Nov 2, 2023
13543a6
better variable control
calypsomatic Nov 2, 2023
2fe681b
add import
calypsomatic Nov 2, 2023
075eaf5
Merge branch 'main' into aj-1188-tdr-consumer
calypsomatic Nov 2, 2023
2c2dccd
Update publish-pacts.yml
calypsomatic Nov 2, 2023
b036911
Update publish-pacts.yml
calypsomatic Nov 2, 2023
5abf60e
Update publish-pacts.yml
calypsomatic Nov 2, 2023
eb67ae1
Merge branch 'main' into aj-1188-tdr-consumer
jladieu Nov 8, 2023
987a183
Check for tables in TDR response.
jladieu Nov 8, 2023
7e45112
Remove unneeded `given` specification.
jladieu Nov 9, 2023
d623989
Remove temp branch from workflow
jladieu Nov 9, 2023
4749f4b
Remove redundant assert.
jladieu Nov 9, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 35 additions & 12 deletions .github/workflows/publish-pacts.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@ on:
push:
branches:
- main
- aj-1188-tdr-consumer
jladieu marked this conversation as resolved.
Show resolved Hide resolved
paths-ignore: [ '**.md' ]

env:
WDS_RUN_ID: ${{ github.event.repository.name }}-${{ github.run_id }}
PACTS_OUTPUT_DIR: service/build/pacts/
PUBLISH_CONTRACT_RUN_NAME: 'publish-contracts-${{ github.event.repository.name }}-${{ github.run_id }}-${{ github.run_attempt }}'

jobs:
init-github-context:
Expand Down Expand Up @@ -49,37 +55,54 @@ jobs:
runs-on: ubuntu-latest
needs: [ init-github-context ]
outputs:
pact-b64: ${{ steps.encode-pact.outputs.pact-b64 }}
pacts-b64: ${{ steps.locate-pacts.outputs.pacts-b64 }}

steps:
- name: Checkout current code
uses: actions/checkout@v3

uses: actions/checkout@v4
- name: Set up JDK
uses: actions/setup-java@v2
with:
java-version: '17'
distribution: 'temurin'
- name: Run consumer tests
run: ./gradlew pactTests
- name: Output consumer contract as non-breaking base64 string
id: encode-pact
- name: Locate all pact json files and output Base64-encoded pacts
id: locate-pacts
run: |
NON_BREAKING_B64=$(cat service/build/pacts/wds-sam.json | base64 -w 0)
echo "pact-b64=${NON_BREAKING_B64}" >> $GITHUB_OUTPUT
# Locate .json pact files in $pactOutputDir
pactPaths=($(find "${{ env.PACTS_OUTPUT_DIR }}" -type f -name "*.json"))
# Put the Base64-encoded pacts in JSON string
pactsB64="["
# Loop through $pactPaths and encode the corresponding pact
for path in "${pactPaths[@]}"; do
nonBreakingB64=$(cat "$path" | base64 -w 0)
pactsB64="${pactsB64}\"$nonBreakingB64\", "
done
# pactPathsJson="${pactPathsJson%, }]"
pactsB64="${pactsB64%, }]"
# echo "pact-paths=$pactPathsJson" >> $GITHUB_OUTPUT
echo "pacts-b64=$pactsB64" >> $GITHUB_OUTPUT

publish-pact-job:
runs-on: ubuntu-latest
needs: [ init-github-context, run-consumer-contract-tests ]
permissions:
contents: 'read'
id-token: 'write'
strategy:
matrix:
pact_b64: ${{ fromJson(needs.run-consumer-contract-tests.outputs.pacts-b64) }}
steps:
- name: Dispatch to terra-github-workflows
uses: broadinstitute/workflow-dispatch@v3
uses: broadinstitute/workflow-dispatch@v4.0.0
with:
run-name: ${{ env.PUBLISH_CONTRACT_RUN_NAME }}
workflow: .github/workflows/publish-contracts.yaml
repo: broadinstitute/terra-github-workflows
ref: refs/heads/main
token: ${{ secrets.BROADBOT_TOKEN }} # github token for access to kick off a job in the private repo
inputs: '{ "pact-b64": "${{ needs.run-consumer-contract-tests.outputs.pact-b64 }}", "repo-owner": "${{ github.repository_owner }}", "repo-name": "${{ github.event.repository.name }}", "repo-branch": "${{ needs.init-github-context.outputs.repo-branch }}" }'
inputs: '{
"run-name": "${{ env.PUBLISH_CONTRACT_RUN_NAME }}",
"pact-b64": "${{ matrix.pact_b64 }}",
"repo-owner": "${{ github.repository_owner }}",
"repo-name": "${{ github.event.repository.name }}",
"repo-branch": "${{ needs.init-github-context.outputs.repo-branch }}"
}'
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
package org.databiosphere.workspacedataservice.pact;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;

import au.com.dius.pact.consumer.MockServer;
import au.com.dius.pact.consumer.dsl.PactDslJsonBody;
import au.com.dius.pact.consumer.dsl.PactDslWithProvider;
import au.com.dius.pact.consumer.junit5.PactConsumerTestExt;
import au.com.dius.pact.consumer.junit5.PactTestFor;
import au.com.dius.pact.core.model.PactSpecVersion;
import au.com.dius.pact.core.model.RequestResponsePact;
import au.com.dius.pact.core.model.annotations.Pact;
import bio.terra.datarepo.model.SnapshotModel;
import java.util.Map;
import java.util.UUID;
import org.databiosphere.workspacedataservice.datarepo.DataRepoClientFactory;
import org.databiosphere.workspacedataservice.datarepo.DataRepoDao;
import org.databiosphere.workspacedataservice.datarepo.DataRepoException;
import org.databiosphere.workspacedataservice.datarepo.HttpDataRepoClientFactory;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

@Tag("pact-test")
@ExtendWith(PactConsumerTestExt.class)
class TDRPactTest {

@BeforeEach
void setUp() {
// Without this setup, the HttpClient throws a "No thread-bound request found" error
MockHttpServletRequest request = new MockHttpServletRequest();
// Set the mock request as the current request context
RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(request));
}

static final String dummySnapshotId = "12345678-abc9-012d-3456-e7fab89cd01e";
okotsopoulos marked this conversation as resolved.
Show resolved Hide resolved
jladieu marked this conversation as resolved.
Show resolved Hide resolved
jladieu marked this conversation as resolved.
Show resolved Hide resolved

@Pact(consumer = "wds", provider = "datarepo")
public RequestResponsePact noSnapshotPact(PactDslWithProvider builder) {
return builder
.given("snapshot doesn't exist", Map.of("id", dummySnapshotId))
.uponReceiving("a snapshot request")
.path("/api/repository/v1/snapshots/" + dummySnapshotId)
.query("include=TABLES")
.method("GET")
.willRespondWith()
.status(404)
jladieu marked this conversation as resolved.
Show resolved Hide resolved
.toPact();
}

@Pact(consumer = "wds", provider = "datarepo")
public RequestResponsePact noAccessToSnapshotPact(PactDslWithProvider builder) {
return builder
.given("user does not have access to snapshot")
calypsomatic marked this conversation as resolved.
Show resolved Hide resolved
.uponReceiving("a snapshot request")
.path("/api/repository/v1/snapshots/" + dummySnapshotId)
.query("include=TABLES")
.method("GET")
.willRespondWith()
.status(403)
jladieu marked this conversation as resolved.
Show resolved Hide resolved
.toPact();
}

@Pact(consumer = "wds", provider = "datarepo")
public RequestResponsePact userHasAccessToSnapshotPact(PactDslWithProvider builder) {
// Current use of datarepo snapshot only relies on id and name
// Future development should update expected response shape to include fields we need
var snapshotResponseShape =
new PactDslJsonBody().stringValue("id", dummySnapshotId).stringType("name");
return builder
.given("user has access to snapshot")
calypsomatic marked this conversation as resolved.
Show resolved Hide resolved
.uponReceiving("a snapshot request")
.path("/api/repository/v1/snapshots/" + dummySnapshotId)
.query("include=TABLES")
jladieu marked this conversation as resolved.
Show resolved Hide resolved
.method("GET")
.willRespondWith()
.status(200)
.body(snapshotResponseShape)
calypsomatic marked this conversation as resolved.
Show resolved Hide resolved
.toPact();
}

@Test
@PactTestFor(pactMethod = "noSnapshotPact", pactVersion = PactSpecVersion.V3)
void testNoSnapshot(MockServer mockServer) {
DataRepoClientFactory clientFactory = new HttpDataRepoClientFactory(mockServer.getUrl());
DataRepoDao dataRepoDao = new DataRepoDao(clientFactory);

assertThrows(
DataRepoException.class,
() -> dataRepoDao.getSnapshot(UUID.fromString("12345678-abc9-012d-3456-e7fab89cd01e")),
"nonexistent snapshot should return 404");
}

@Test
@PactTestFor(pactMethod = "noAccessToSnapshotPact", pactVersion = PactSpecVersion.V3)
void testNoAccessToSnapshot(MockServer mockServer) {
DataRepoClientFactory clientFactory = new HttpDataRepoClientFactory(mockServer.getUrl());
DataRepoDao dataRepoDao = new DataRepoDao(clientFactory);

assertThrows(
DataRepoException.class,
() -> dataRepoDao.getSnapshot(UUID.fromString("12345678-abc9-012d-3456-e7fab89cd01e")),
jladieu marked this conversation as resolved.
Show resolved Hide resolved
"nonexistent snapshot should return 403");
}

@Test
@PactTestFor(pactMethod = "userHasAccessToSnapshotPact", pactVersion = PactSpecVersion.V3)
void testUserHasAccessToSnapshot(MockServer mockServer) {
DataRepoClientFactory clientFactory = new HttpDataRepoClientFactory(mockServer.getUrl());
DataRepoDao dataRepoDao = new DataRepoDao(clientFactory);

SnapshotModel snapshot =
dataRepoDao.getSnapshot(UUID.fromString("12345678-abc9-012d-3456-e7fab89cd01e"));
assertNotNull(snapshot, "Snapshot request should return a snapshot");
assertNotNull(snapshot.getId(), "Snapshot response should have an id");
jladieu marked this conversation as resolved.
Show resolved Hide resolved
assertNotNull(snapshot.getName(), "Snapshot response should have a name");
assertEquals(UUID.fromString(dummySnapshotId), snapshot.getId());
}
}
Loading