-
Notifications
You must be signed in to change notification settings - Fork 1
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
DEVEXP-530: Conversation e2e tests (Apps) #135
Changes from all commits
75a7379
751ec57
5db2ca1
f6a1488
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
name: Building Java SDK | ||
|
||
on: [push] | ||
|
||
jobs: | ||
build: | ||
|
||
runs-on: ubuntu-latest | ||
|
||
steps: | ||
- uses: actions/checkout@v3 | ||
- name: Set up JDK | ||
uses: actions/setup-java@v3 | ||
with: | ||
java-version: '21' | ||
distribution: 'temurin' | ||
cache: maven | ||
- name: Build with Maven | ||
run: mvn -B -DskipITs clean package javadoc:javadoc --file pom.xml | ||
|
||
# Optional: Uploads the full dependency graph to GitHub to improve the quality of Dependabot alerts this repository can receive | ||
- name: Update dependency graph | ||
uses: advanced-security/maven-dependency-submission-action@571e99aab1055c2e71a1e2309b9691de18d6b7d6 | ||
|
||
e2e-tests: | ||
needs: build | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v3 | ||
- name: Set up JDK | ||
uses: actions/setup-java@v3 | ||
with: | ||
java-version: '21' | ||
distribution: 'temurin' | ||
cache: maven | ||
- name: Checkout sinch-sdk-mockserver repository | ||
uses: actions/checkout@v3 | ||
with: | ||
repository: sinch/sinch-sdk-mockserver | ||
token: ${{ secrets.MOCKSERVER_REPO_PAT_CI }} | ||
fetch-depth: 0 | ||
path: sinch-sdk-mockserver | ||
|
||
- name: Build custom Docker image | ||
run: | | ||
cd sinch-sdk-mockserver | ||
docker build -t sinch-sdk-mockserver -f Dockerfile . | ||
|
||
- name: Install Docker Compose | ||
run: | | ||
sudo apt-get update | ||
sudo apt-get install -y docker-compose | ||
|
||
- name: Start mock servers with Docker Compose | ||
run: | | ||
cd sinch-sdk-mockserver | ||
docker-compose up -d | ||
|
||
- name: Wait for the mock servers to be healthy | ||
run: | | ||
cd sinch-sdk-mockserver | ||
. ./scripts/healthcheck.sh | ||
|
||
- name: Link to feature files | ||
run: | | ||
ln -s ${{ github.workspace }}/sinch-sdk-mockserver/features client/src/test/resources | ||
|
||
- name: Run e2e tests | ||
run: mvn -B -DskipUTs -Dspotless.check.skip=true verify --file pom.xml |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package com.sinch.sdk.e2e; | ||
|
||
import com.sinch.sdk.SinchClient; | ||
import com.sinch.sdk.models.Configuration; | ||
import com.sinch.sdk.models.ConversationContext; | ||
import com.sinch.sdk.models.ConversationRegion; | ||
|
||
public class Config { | ||
|
||
public static final String PROJECT_ID = "tinyfrog-jump-high-over-lilypadbasin"; | ||
public static final String KEY_ID = "'keyId"; | ||
public static final String KEY_SECRET = "keySecret"; | ||
public static final String AUTH_URL = "http://localhost:3011/oauth2/token"; | ||
public static final String CONVERSATION_HOST_NAME = "http://localhost:3014"; | ||
public static final ConversationRegion CONVERSATION_REGION = ConversationRegion.US; | ||
|
||
private final SinchClient client; | ||
|
||
private Config() { | ||
|
||
Configuration configuration = | ||
Configuration.builder() | ||
.setOAuthUrl(Config.AUTH_URL) | ||
.setProjectId(Config.PROJECT_ID) | ||
.setKeyId(Config.KEY_ID) | ||
.setKeySecret(Config.KEY_SECRET) | ||
.setConversationContext( | ||
ConversationContext.builder() | ||
.setUrl(Config.CONVERSATION_HOST_NAME) | ||
.setRegion(Config.CONVERSATION_REGION) | ||
.build()) | ||
.build(); | ||
|
||
client = new SinchClient(configuration); | ||
} | ||
|
||
private static class LazyHolder { | ||
private static final Config INSTANCE = new Config(); | ||
} | ||
|
||
public static SinchClient getSinchClient() { | ||
return LazyHolder.INSTANCE.client; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
package com.sinch.sdk.e2e.domains.conversation; | ||
|
||
import com.sinch.sdk.domains.conversation.api.v1.AppService; | ||
import com.sinch.sdk.domains.conversation.models.v1.ProcessingMode; | ||
import com.sinch.sdk.domains.conversation.models.v1.app.ConversationMetadataReportView; | ||
import com.sinch.sdk.domains.conversation.models.v1.app.request.AppCreateRequest; | ||
import com.sinch.sdk.domains.conversation.models.v1.app.request.AppUpdateRequest; | ||
import com.sinch.sdk.domains.conversation.models.v1.app.request.ConversationChannelCredentialRequest; | ||
import com.sinch.sdk.domains.conversation.models.v1.app.request.ConversationChannelCredentialsRequestBuilderFactory; | ||
import com.sinch.sdk.domains.conversation.models.v1.app.response.AppResponse; | ||
import com.sinch.sdk.domains.conversation.models.v1.credentials.ChannelIntegrationStatus; | ||
import com.sinch.sdk.domains.conversation.models.v1.credentials.StaticBearerCredentials; | ||
import com.sinch.sdk.e2e.Config; | ||
import io.cucumber.java.en.Given; | ||
import io.cucumber.java.en.Then; | ||
import io.cucumber.java.en.When; | ||
import java.util.Arrays; | ||
import java.util.Collection; | ||
import org.junit.jupiter.api.Assertions; | ||
|
||
public class AppsSteps { | ||
|
||
AppService service; | ||
AppResponse createResponse; | ||
Collection<AppResponse> listResponse; | ||
AppResponse getResponse; | ||
AppResponse updateResponse; | ||
boolean deletePassed; | ||
|
||
@Given("^the Conversation service \"Apps\" is available$") | ||
public void serviceAvailable() { | ||
service = Config.getSinchClient().conversation().v1().app(); | ||
} | ||
|
||
@When("^I send a request to create an app$") | ||
public void create() { | ||
|
||
String identity = "SpaceMonkeySquadron"; | ||
String token = "00112233445566778899aabbccddeeff"; | ||
String displayName = "E2E Conversation App"; | ||
|
||
ConversationChannelCredentialRequest credentials = | ||
ConversationChannelCredentialsRequestBuilderFactory.sms( | ||
StaticBearerCredentials.builder() | ||
.setClaimedIdentity(identity) | ||
.setToken(token) | ||
.build()) | ||
.build(); | ||
|
||
AppCreateRequest request = | ||
AppCreateRequest.builder() | ||
.setChannelCredentials(Arrays.asList(credentials)) | ||
.setDisplayName(displayName) | ||
.build(); | ||
|
||
createResponse = service.create(request); | ||
} | ||
|
||
@When("^I send a request to list all the apps$") | ||
public void list() { | ||
|
||
listResponse = service.list(); | ||
} | ||
|
||
@When("^I send a request to retrieve an app$") | ||
public void get() { | ||
|
||
getResponse = service.get("foo"); | ||
} | ||
|
||
@When("^I send a request to update an app$") | ||
public void update() { | ||
|
||
AppUpdateRequest request = | ||
AppUpdateRequest.builder().setDisplayName(" a new display name").build(); | ||
updateResponse = service.update("foo", request); | ||
} | ||
|
||
@When("^I send a request to delete an app$") | ||
public void delete() { | ||
|
||
service.delete("foo"); | ||
deletePassed = true; | ||
} | ||
|
||
@Then("the conversation app is created") | ||
public void createResult() { | ||
checkExpectedAppResponseCommonFields(createResponse); | ||
Assertions.assertEquals( | ||
createResponse.getChannelCredentials().get(0).getState().getStatus(), | ||
ChannelIntegrationStatus.PENDING); | ||
} | ||
|
||
@Then("the apps list contains {int} apps") | ||
public void listResult(int size) { | ||
|
||
Assertions.assertEquals(listResponse.size(), size); | ||
AppResponse item = listResponse.stream().findFirst().orElse(null); | ||
|
||
checkExpectedAppResponseCommonFields(item); | ||
Assertions.assertEquals(item.getDisplayName(), "E2E Conversation App"); | ||
Assertions.assertEquals( | ||
item.getChannelCredentials().get(0).getState().getStatus(), | ||
ChannelIntegrationStatus.ACTIVE); | ||
item = listResponse.stream().reduce((first, second) -> second).orElse(null); | ||
Assertions.assertEquals(item.getId(), "01W4FFL35P4NC4K35CONVAPP002"); | ||
} | ||
|
||
@Then("the response contains the app details") | ||
public void getResult() { | ||
checkExpectedAppResponseCommonFields(getResponse); | ||
Assertions.assertEquals(getResponse.getDisplayName(), "E2E Conversation App"); | ||
Assertions.assertEquals( | ||
getResponse.getChannelCredentials().get(0).getState().getStatus(), | ||
ChannelIntegrationStatus.ACTIVE); | ||
} | ||
|
||
@Then("the response contains the app details with updated properties") | ||
public void updateResult() { | ||
checkExpectedAppResponseCommonFields(updateResponse); | ||
Assertions.assertEquals(updateResponse.getDisplayName(), "Updated name"); | ||
Assertions.assertEquals( | ||
updateResponse.getChannelCredentials().get(0).getState().getStatus(), | ||
ChannelIntegrationStatus.ACTIVE); | ||
} | ||
|
||
@Then("the delete app response contains no data") | ||
public void deleteResult() { | ||
|
||
Assertions.assertTrue(deletePassed); | ||
} | ||
|
||
void checkExpectedAppResponseCommonFields(AppResponse appResponse) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a nice idea to factorize the check on common fields. But some tests can break if we change some data in the mockserver expectations. I've tried to create some consistency when I wrote them. Let's agree together to keep it like this! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. According to our discussion: we agree to update tests accordingly in case of future change |
||
Assertions.assertEquals(appResponse.getId(), "01W4FFL35P4NC4K35CONVAPP001"); | ||
Assertions.assertEquals(appResponse.getChannelCredentials().size(), 1); | ||
Assertions.assertEquals( | ||
appResponse.getConversationMetadataReportView(), ConversationMetadataReportView.NONE); | ||
Assertions.assertEquals(appResponse.getProcessingMode(), ProcessingMode.CONVERSATION); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package com.sinch.sdk.e2e.domains.conversation; | ||
|
||
import org.junit.platform.suite.api.IncludeEngines; | ||
import org.junit.platform.suite.api.SelectClasspathResource; | ||
import org.junit.platform.suite.api.Suite; | ||
|
||
@Suite | ||
@IncludeEngines("cucumber") | ||
@SelectClasspathResource("features/conversation/apps.feature") | ||
public class ConversationIT {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here you are just checking that the request completed without exception right?
Note that if we decide to move to static values instead of regexp for parameter matching, this test will fail as
foo
is certainly not a value corresponding to an appId. You may reuse the one tou are already checking in the common fieldsThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
According to our discussion: we agree to update tests accordingly in case of future change