Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,12 @@ class FSConnectorTest extends CommonTest{
String code
String denyResponse
Response consentResponse
Response consentUpdateResponse
Response consentRevocationResponse
Response consentValidateResponse
Response accountValidationResponse
String consentPath
String consentUpdatePath
String initiationPayload
String initiationIncorrectPayload = RequestPayloads.initiationIncorrectPayload
String initiationPayloadPayloadWithoutReadAccountsDetail = RequestPayloads.initiationPayloadWithoutReadAccountsDetail
Expand Down Expand Up @@ -702,6 +704,18 @@ class FSConnectorTest extends CommonTest{
return consentRevocationResponse
}

/**
* Account Consent Update.
*/
void doConsentUpdate(String payload, String consentId) {

consentUpdateResponse = consentRequestBuilder.buildKeyManagerRequest(configuration.getAppInfoClientID())
.header(ConnectorTestConstants.X_WSO2_INTERNAL_HEADER, "true")
.body(payload)
.baseUri(configuration.getISServerUrl())
.put(consentUpdatePath + "/${consentId}")
}

/**Consent Authorisation.
*
* @param clientId
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,37 @@ class AccountsRequestPayloads {
}
""".stripIndent()

static String getAccountConsentUpdatePayload(String consentId) {
return """
{
"consentID": "${consentId}",
"status": "AwaitingAuthorisation",
"validityPeriod": ${ConnectorTestConstants.expirationInstant.toEpochSecond()},
"recurringIndicator": true,
"consentFrequency": 0,
"receipt": "{\\"Data\\": {\\"Permissions\\": [\\"ReadAccountsBasic\\",\\"ReadAccountsDetail\\",\\"ReadBalances\\"],\\"ExpirationDateTime\\": \\"2026-03-17T15:43:35.946770+05:30\\",\\"TransactionFromDateTime\\": \\"2026-03-12T15:43:35.947399+05:30\\",\\"TransactionToDateTime\\": \\"2026-03-15T15:43:35.947514+05:30\\"},\\"Risk\\": { }}",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shall we use the datetime variables defined at the beginning of the class without hard coding them. This may fail after sometime.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 285950a

"consentAttributes": {
"key1": "value1",
"key2": "value2"
},
"authorizationResources": [
{
"userID": "admin@wso2.com",
"authorizationType": "auth",
"authorizationStatus": "Created",
"resources": [
{
"accountID": "1962368",
"permission": "account",
"mappingStatus": "active"
}
]
}
]
}
""".stripIndent()
}

/**
* Build Validation Payload
* @param clientId - Client Id
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ class ConnectorTestConstants extends Constants{
public static final String PAYMENTS_TYPE = "payments"
public static final String COF_TYPE = "cof"
public static final String X_WSO2_MUTUAL_CERT = "x-wso2-mutual-auth-cert"
public static final String X_WSO2_INTERNAL_HEADER = "x-wso2-internal-request"
public static final String CHARSET = "charset"
public static final String CHARSET_TYPE = "UTF-8"
public static final String X_FAPI_INTERACTION_ID = "x-fapi-interaction-id"
Expand Down Expand Up @@ -217,6 +218,7 @@ class ConnectorTestConstants extends Constants{
static final String IS_VALID = "isValid"
static final String CONSENT_ID_INVALID_ERROR = "Consent ID invalid"
static final String API_REQUEST_NOT_FOUND = "No matching resource found for given API Request"
static final String CONSENT_UPDATE_PATH = CONSENT_API + "/consent"

//Internal Rest API Url
static final String SP_INTERNAL_ENDPOINT = "/t/carbon.super/api/server/v1/applications"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,308 @@
/**
* Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com).
*
* WSO2 LLC. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.wso2.financial.services.accelerator.is.test.consent.management.ConsentOperationsFlowTests

import io.restassured.http.ContentType
import io.restassured.response.Response
import org.json.JSONObject
import org.testng.Assert
import org.testng.annotations.BeforeClass
import org.testng.annotations.Test
import org.wso2.financial.services.accelerator.test.framework.FSConnectorTest
import org.wso2.financial.services.accelerator.test.framework.constant.AccountsRequestPayloads
import org.wso2.financial.services.accelerator.test.framework.constant.ConnectorTestConstants
import org.wso2.financial.services.accelerator.test.framework.request_builder.ConsentRequestBuilder
import org.wso2.financial.services.accelerator.test.framework.utility.ConsentMgtTestUtils
import org.wso2.financial.services.accelerator.test.framework.utility.FSRestAsRequestBuilder
import org.wso2.financial.services.accelerator.test.framework.utility.TestUtil

/**
* Basic Consent Update Flow Tests.
*/
class InternalConsentManageFlowValidationTest extends FSConnectorTest {

String updatePayload
ConsentRequestBuilder consentRequestBuilder = new ConsentRequestBuilder()
String authIdBeforeUpdate
String mappingIdBeforeUpdate

@BeforeClass
void init() {
consentPath = ConnectorTestConstants.ACCOUNT_CONSENT_PATH
initiationPayload = AccountsRequestPayloads.initiationPayload
consentUpdatePath = ConnectorTestConstants.CONSENT_UPDATE_PATH

doDefaultInitiation()
Assert.assertNotNull(consentId)
Assert.assertEquals(consentResponse.getStatusCode(), ConnectorTestConstants.STATUS_CODE_201)

doConsentRetrieval(consentId)
Assert.assertNotNull(consentId)
Assert.assertEquals(consentResponse.getStatusCode(), ConnectorTestConstants.STATUS_CODE_200)
Assert.assertEquals(TestUtil.parseResponseBody(consentResponse, "Data.Status"), "AwaitingAuthorisation")

updatePayload = AccountsRequestPayloads.getAccountConsentUpdatePayload(consentId)
}

@Test(priority = 1)
void "Verify internal retrieval of a Created Consent"() {

consentResponse = consentRequestBuilder.buildKeyManagerRequest(configuration.getAppInfoClientID())
.header(ConnectorTestConstants.X_WSO2_INTERNAL_HEADER, "true")
.baseUri(configuration.getISServerUrl())
.get(consentPath + "/${consentId}")
Assert.assertNotNull(consentId)
Assert.assertEquals(consentResponse.getStatusCode(), ConnectorTestConstants.STATUS_CODE_200)
Assert.assertNotNull(TestUtil.parseResponseBody(consentResponse, "updatedTime"))
Assert.assertNotNull(TestUtil.parseResponseBody(consentResponse, "consentID"))
Assert.assertNotNull(TestUtil.parseResponseBody(consentResponse, "clientID"))
Assert.assertEquals(TestUtil.parseResponseBody(consentResponse, "status"),
"AwaitingAuthorisation")
Assert.assertNotNull(TestUtil.parseResponseBody(consentResponse, "authorizationResources"))
List<JSONObject> authorizationResources = extractListFromResponse(consentResponse, "authorizationResources")
authIdBeforeUpdate = authorizationResources.get(0).get("authorizationID")
}
Comment on lines +78 to +80
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Assert list non-emptiness before indexing into authorizationResources/resources.

At Line 79/93/118/139 you index with .get(0) after only null checks. If the API returns an empty list, the test fails with IndexOutOfBoundsException instead of a meaningful assertion.

✅ Proposed fix pattern
         List<JSONObject> authorizationResources = extractListFromResponse(consentResponse, "authorizationResources")
+        Assert.assertFalse(authorizationResources.isEmpty(), "authorizationResources is empty")
         authIdBeforeUpdate = authorizationResources.get(0).get("authorizationID")
         List<JSONObject> resources = authorizationResources.get(0).get("resources") as List<JSONObject>
         Assert.assertNotNull(resources)
+        Assert.assertFalse(resources.isEmpty(), "resources is empty")
         mappingIdBeforeUpdate = resources.get(0).get("mappingID")

Also applies to: 92-94, 117-121, 134-140

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@fs-integration-test-suite/accelerator-tests/is-tests/consent-management/src/test/groovy/org/wso2/financial/services/accelerator/is/test/consent/management/ConsentOperationsFlowTests/InternalConsentManageFlowValidationTest.groovy`
around lines 78 - 80, The tests call extractListFromResponse(...) to obtain
authorizationResources and then immediately use authorizationResources.get(0)
(e.g., to set authIdBeforeUpdate) without asserting the list is non-empty; add
an explicit assertion (e.g., assert authorizationResources != null &&
!authorizationResources.isEmpty()) immediately after each
extractListFromResponse call (locations around authorizationResources variable
usage and before any authorizationResources.get(0) access in
InternalConsentManageFlowValidationTest) to fail with a clear message instead of
throwing IndexOutOfBoundsException. Ensure the assertion message clarifies which
response was empty (authorizationResources) and apply this fix to all
occurrences where .get(0) is used (the blocks that set authIdBeforeUpdate and
similar usages).


@Test(priority = 1, dependsOnMethods = "Verify internal retrieval of a Created Consent")
void "Verify internal updating a Created Consent"() {

doConsentUpdate(updatePayload, consentId)
Assert.assertNotNull(consentId)
Assert.assertEquals(consentUpdateResponse.getStatusCode(), ConnectorTestConstants.STATUS_CODE_200)
Assert.assertNotNull(TestUtil.parseResponseBody(consentUpdateResponse, "updatedTime"))
Assert.assertNotNull(TestUtil.parseResponseBody(consentUpdateResponse, "consentID"))
Assert.assertNotNull(TestUtil.parseResponseBody(consentUpdateResponse, "clientID"))
Assert.assertNotNull(TestUtil.parseResponseBody(consentUpdateResponse, "authorizationResources"))
List<JSONObject> authorizationResources = extractListFromResponse(consentUpdateResponse, "authorizationResources")
String newAuthId = authorizationResources.get(0).get("authorizationID")
Assert.assertNotEquals(newAuthId, authIdBeforeUpdate)
}

@Test(priority = 1, dependsOnMethods = "Verify internal updating a Created Consent")
void "Verify internal retrieval of a Created Consent after authorization"() {

// Authorise Consent
List<ConnectorTestConstants.ApiScope> scopeList = ConsentMgtTestUtils
.getApiScopesForConsentType(ConnectorTestConstants.ACCOUNTS_TYPE)
doConsentAuthorisation(configuration.getAppInfoClientID(), true, scopeList)

consentResponse = consentRequestBuilder.buildKeyManagerRequest(configuration.getAppInfoClientID())
.header(ConnectorTestConstants.X_WSO2_INTERNAL_HEADER, "true")
.baseUri(configuration.getISServerUrl())
.get(consentPath + "/${consentId}")
Assert.assertNotNull(consentId)
Assert.assertEquals(consentResponse.getStatusCode(), ConnectorTestConstants.STATUS_CODE_200)
Assert.assertNotNull(TestUtil.parseResponseBody(consentResponse, "updatedTime"))
Assert.assertNotNull(TestUtil.parseResponseBody(consentResponse, "consentID"))
Assert.assertNotNull(TestUtil.parseResponseBody(consentResponse, "clientID"))
Assert.assertEquals(TestUtil.parseResponseBody(consentResponse, "status"),
"Authorised")
Assert.assertNotNull(TestUtil.parseResponseBody(consentResponse, "authorizationResources"))
List<JSONObject> authorizationResources = extractListFromResponse(consentResponse, "authorizationResources")
authIdBeforeUpdate = authorizationResources.get(0).get("authorizationID")
List<JSONObject> resources = authorizationResources.get(0).get("resources") as List<JSONObject>
Assert.assertNotNull(resources)
mappingIdBeforeUpdate = resources.get(0).get("mappingID")
}

@Test(priority = 1, dependsOnMethods = "Verify internal retrieval of a Created Consent after authorization")
void "Verify internal updating a Created Consent after authorization"() {

doConsentUpdate(updatePayload, consentId)
Assert.assertNotNull(consentId)
Assert.assertEquals(consentUpdateResponse.getStatusCode(), ConnectorTestConstants.STATUS_CODE_200)
Assert.assertNotNull(TestUtil.parseResponseBody(consentUpdateResponse, "updatedTime"))
Assert.assertNotNull(TestUtil.parseResponseBody(consentUpdateResponse, "consentID"))
Assert.assertNotNull(TestUtil.parseResponseBody(consentUpdateResponse, "clientID"))
Assert.assertNotNull(TestUtil.parseResponseBody(consentUpdateResponse, "authorizationResources"))
List<JSONObject> authorizationResources = extractListFromResponse(consentUpdateResponse, "authorizationResources")
String newAuthId = authorizationResources.get(0).get("authorizationID")
Assert.assertNotEquals(newAuthId, authIdBeforeUpdate)
List<JSONObject> resources = authorizationResources.get(0).get("resources") as List<JSONObject>
Assert.assertNotNull(resources)
String newMappingId = resources.get(0).get("mappingID")
Assert.assertNotEquals(newMappingId, mappingIdBeforeUpdate)
}

@Test
void "Verify internal retrieval of a Created Consent without Authorization header"() {

consentUpdateResponse = FSRestAsRequestBuilder.buildRequest()
.header(ConnectorTestConstants.X_FAPI_FINANCIAL_ID, ConnectorTestConstants.X_FAPI_FINANCIAL_ID_VALUE)
.header(ConnectorTestConstants.X_WSO2_CLIENT_ID_KEY, "${configuration.getAppInfoClientID()}")
.header(ConnectorTestConstants.X_FAPI_INTERACTION_ID, UUID.randomUUID().toString())
.header(ConnectorTestConstants.X_WSO2_INTERNAL_HEADER, "true")
.baseUri(configuration.getISServerUrl())
.get(consentPath + "/${consentId}")

Assert.assertNotNull(consentId)
Assert.assertEquals(consentUpdateResponse.getStatusCode(), ConnectorTestConstants.STATUS_CODE_401)
}

@Test
void "Verify internal consent retrieval With Invalid Authorization Header"() {

def basicHeader = getBasicAuthHeader(configuration.getUserPSUName(),
configuration.getUserPSUPWD())

consentUpdateResponse = FSRestAsRequestBuilder.buildRequest()
.header(ConnectorTestConstants.X_FAPI_FINANCIAL_ID, ConnectorTestConstants.X_FAPI_FINANCIAL_ID_VALUE)
.header(ConnectorTestConstants.X_WSO2_CLIENT_ID_KEY, "${configuration.getAppInfoClientID()}")
.header(ConnectorTestConstants.X_FAPI_INTERACTION_ID, UUID.randomUUID().toString())
.header(ConnectorTestConstants.X_WSO2_INTERNAL_HEADER, "true")
.header(ConnectorTestConstants.AUTHORIZATION_HEADER, basicHeader)
.baseUri(configuration.getISServerUrl())
.get(consentPath + "/${consentId}")

Assert.assertNotNull(consentId)
Assert.assertEquals(consentUpdateResponse.getStatusCode(), ConnectorTestConstants.STATUS_CODE_403)
}

@Test
void "Verify internal consent retrieval without client ID"() {

consentResponse = buildKeyManagerRequest("")
.header(ConnectorTestConstants.AUTHORIZATION_HEADER, "${GenerateBasicHeader()}")
.header(ConnectorTestConstants.X_WSO2_INTERNAL_HEADER, "true")
.baseUri(configuration.getISServerUrl())
.get(consentPath + "/${consentId}")

Assert.assertEquals(consentResponse.getStatusCode(), ConnectorTestConstants.STATUS_CODE_400)
}

@Test
void "Verify internal consent retrieval with invalid client ID"() {

consentResponse = buildKeyManagerRequest("tyionwbbvqhhwvh")
.header(ConnectorTestConstants.AUTHORIZATION_HEADER, "${GenerateBasicHeader()}")
.header(ConnectorTestConstants.X_WSO2_INTERNAL_HEADER, "true")
.baseUri(configuration.getISServerUrl())
.get(consentPath + "/${consentId}")

Assert.assertEquals(consentResponse.getStatusCode(), ConnectorTestConstants.STATUS_CODE_400)
}

@Test
void "Verify updating a Created Consent without consent ID"() {

consentUpdateResponse = consentRequestBuilder.buildKeyManagerRequest(configuration.getAppInfoClientID())
.header(ConnectorTestConstants.X_WSO2_INTERNAL_HEADER, "true")
.body(updatePayload)
.baseUri(configuration.getISServerUrl())
.put(consentUpdatePath + "/")

Assert.assertEquals(consentUpdateResponse.getStatusCode(), ConnectorTestConstants.STATUS_CODE_400)
}

@Test
void "Verify updating a Created Consent without Authorization header"() {

consentUpdateResponse = FSRestAsRequestBuilder.buildRequest()
.contentType(ContentType.JSON)
.header(ConnectorTestConstants.X_FAPI_FINANCIAL_ID, ConnectorTestConstants.X_FAPI_FINANCIAL_ID_VALUE)
.header(ConnectorTestConstants.X_WSO2_CLIENT_ID_KEY, "${configuration.getAppInfoClientID()}")
.header(ConnectorTestConstants.X_FAPI_INTERACTION_ID, UUID.randomUUID().toString())
.header(ConnectorTestConstants.X_WSO2_INTERNAL_HEADER, "true")
.baseUri(configuration.getISServerUrl())
.body(updatePayload)
.put(consentUpdatePath + "/${consentId}")

Assert.assertNotNull(consentId)
Assert.assertEquals(consentUpdateResponse.getStatusCode(), ConnectorTestConstants.STATUS_CODE_401)
}

@Test
void "Get Accounts Initiation With Invalid Authorization Header"() {

def basicHeader = getBasicAuthHeader(configuration.getUserPSUName(),
configuration.getUserPSUPWD())

consentUpdateResponse = FSRestAsRequestBuilder.buildRequest()
.contentType(ContentType.JSON)
.header(ConnectorTestConstants.X_FAPI_FINANCIAL_ID, ConnectorTestConstants.X_FAPI_FINANCIAL_ID_VALUE)
.header(ConnectorTestConstants.X_WSO2_CLIENT_ID_KEY, "${configuration.getAppInfoClientID()}")
.header(ConnectorTestConstants.X_FAPI_INTERACTION_ID, UUID.randomUUID().toString())
.header(ConnectorTestConstants.X_WSO2_INTERNAL_HEADER, "true")
.header(ConnectorTestConstants.AUTHORIZATION_HEADER, basicHeader)
.baseUri(configuration.getISServerUrl())
.body(updatePayload)
.put(consentUpdatePath + "/${consentId}")

Assert.assertNotNull(consentId)
Assert.assertEquals(consentUpdateResponse.getStatusCode(), ConnectorTestConstants.STATUS_CODE_403)
}

@Test
void "Verify updating a Created Consent with Incorrect request path"() {

consentUpdateResponse = consentRequestBuilder.buildKeyManagerRequest(configuration.getAppInfoClientID())
.header(ConnectorTestConstants.X_WSO2_INTERNAL_HEADER, "true")
.baseUri(configuration.getISServerUrl())
.body(updatePayload)
.put(incorrectConsentPath + "/${consentId}")

Assert.assertNotNull(consentId)
Assert.assertEquals(consentUpdateResponse.getStatusCode(), ConnectorTestConstants.STATUS_CODE_401)
}

@Test
void "Verify updating a Created Consent with incorrect Consent ID"() {

String incorrectConsentID = 'c1b6c5c9-1ec9-4ccf-8f68-e18df87777bfaaa'

consentUpdateResponse = consentRequestBuilder.buildKeyManagerRequest(configuration.getAppInfoClientID())
.header(ConnectorTestConstants.X_WSO2_INTERNAL_HEADER, "true")
.baseUri(configuration.getISServerUrl())
.body(updatePayload)
.put(consentUpdatePath + "/${incorrectConsentID}")
Assert.assertNotNull(consentId)
Assert.assertEquals(consentUpdateResponse.getStatusCode(), ConnectorTestConstants.STATUS_CODE_400)
}

@Test
void "Verify Consent updating without client ID"() {

consentResponse = buildKeyManagerRequest("")
.header(ConnectorTestConstants.AUTHORIZATION_HEADER, "${GenerateBasicHeader()}")
.header(ConnectorTestConstants.X_WSO2_INTERNAL_HEADER, "true")
.body(updatePayload)
.baseUri(configuration.getISServerUrl())
.put(consentUpdatePath + "/${consentId}")

Assert.assertEquals(consentResponse.getStatusCode(), ConnectorTestConstants.STATUS_CODE_400)
}

@Test
void "Verify Consent updating with invalid client ID"() {

consentResponse = buildKeyManagerRequest("tyionwbbvqhhwvh")
.header(ConnectorTestConstants.AUTHORIZATION_HEADER, "${GenerateBasicHeader()}")
.header(ConnectorTestConstants.X_WSO2_INTERNAL_HEADER, "true")
.body(updatePayload)
.baseUri(configuration.getISServerUrl())
.put(consentUpdatePath + "/${consentId}")

Assert.assertEquals(consentResponse.getStatusCode(), ConnectorTestConstants.STATUS_CODE_400)
}

static List<JSONObject> extractListFromResponse(Response response, String jsonPath) {
return response.jsonPath().getList(jsonPath)
}

}
Loading
Loading