From 493a7858e0550466b91b0ff6f88195f35a830973 Mon Sep 17 00:00:00 2001 From: hongwei Date: Fri, 23 Jan 2026 12:37:21 +0100 Subject: [PATCH] test/(http4s): add ResourceDocMatcher unit tests - Add comprehensive test suite for ResourceDocMatcher with 545 lines of test coverage - Test exact path matching for GET, POST, and multi-segment paths - Test verb and path mismatch scenarios returning None - Test BANK_ID variable matching and parameter extraction - Test BANK_ID + ACCOUNT_ID variable matching and extraction - Test BANK_ID + ACCOUNT_ID + VIEW_ID variable matching and extraction - Test COUNTERPARTY_ID variable matching and extraction - Test non-matching request scenarios - Ensure ResourceDocMatcher correctly identifies and extracts path parameters for all variable types - Use FeatureSpec with Given-When-Then style for clear test documentation --- .../util/http4s/ResourceDocMatcherTest.scala | 545 ++++++++++++++++++ 1 file changed, 545 insertions(+) create mode 100644 obp-api/src/test/scala/code/api/util/http4s/ResourceDocMatcherTest.scala diff --git a/obp-api/src/test/scala/code/api/util/http4s/ResourceDocMatcherTest.scala b/obp-api/src/test/scala/code/api/util/http4s/ResourceDocMatcherTest.scala new file mode 100644 index 000000000..a686295aa --- /dev/null +++ b/obp-api/src/test/scala/code/api/util/http4s/ResourceDocMatcherTest.scala @@ -0,0 +1,545 @@ +package code.api.util.http4s + +import code.api.util.APIUtil.ResourceDoc +import code.api.util.ApiTag.ResourceDocTag +import com.openbankproject.commons.util.ApiVersion +import net.liftweb.json.JsonAST.JObject +import org.http4s._ +import org.scalatest.{FeatureSpec, GivenWhenThen, Matchers, Tag} + +import scala.collection.mutable.ArrayBuffer + +/** + * Unit tests for ResourceDocMatcher + * + * Tests ResourceDoc matching and path parameter extraction: + * - Matching by verb and exact path + * - Matching with BANK_ID variable + * - Matching with BANK_ID + ACCOUNT_ID variables + * - Matching with BANK_ID + ACCOUNT_ID + VIEW_ID variables + * - Matching with COUNTERPARTY_ID variable + * - Non-matching requests return None + * - Path parameter extraction for all variable types + * + */ +class ResourceDocMatcherTest extends FeatureSpec with Matchers with GivenWhenThen { + + object ResourceDocMatcherTag extends Tag("ResourceDocMatcher") + + // Helper to create minimal ResourceDoc for testing + private def createResourceDoc( + verb: String, + url: String, + operationId: String = "testOperation" + ): ResourceDoc = { + ResourceDoc( + partialFunction = null, // Not needed for matching tests + implementedInApiVersion = ApiVersion.v7_0_0, + partialFunctionName = operationId, + requestVerb = verb, + requestUrl = url, + summary = "Test endpoint", + description = "Test description", + exampleRequestBody = JObject(Nil), + successResponseBody = JObject(Nil), + errorResponseBodies = List.empty, + tags = List(ResourceDocTag("test")), + roles = None + ) + } + + feature("ResourceDocMatcher - Exact path matching") { + + scenario("Match GET request with exact path", ResourceDocMatcherTag) { + Given("A ResourceDoc for GET /banks") + val resourceDocs = ArrayBuffer( + createResourceDoc("GET", "/banks", "getBanks") + ) + + When("Matching a GET request to /obp/v7.0.0/banks") + val path = Uri.Path.unsafeFromString("/obp/v7.0.0/banks") + val result = ResourceDocMatcher.findResourceDoc("GET", path, resourceDocs) + + Then("Should find the matching ResourceDoc") + result should be(defined) + result.get.partialFunctionName should equal("getBanks") + } + + scenario("Match POST request with exact path", ResourceDocMatcherTag) { + Given("A ResourceDoc for POST /banks") + val resourceDocs = ArrayBuffer( + createResourceDoc("POST", "/banks", "createBank") + ) + + When("Matching a POST request to /obp/v7.0.0/banks") + val path = Uri.Path.unsafeFromString("/obp/v7.0.0/banks") + val result = ResourceDocMatcher.findResourceDoc("POST", path, resourceDocs) + + Then("Should find the matching ResourceDoc") + result should be(defined) + result.get.partialFunctionName should equal("createBank") + } + + scenario("Match request with multi-segment path", ResourceDocMatcherTag) { + Given("A ResourceDoc for GET /management/metrics") + val resourceDocs = ArrayBuffer( + createResourceDoc("GET", "/management/metrics", "getMetrics") + ) + + When("Matching a GET request to /obp/v7.0.0/management/metrics") + val path = Uri.Path.unsafeFromString("/obp/v7.0.0/management/metrics") + val result = ResourceDocMatcher.findResourceDoc("GET", path, resourceDocs) + + Then("Should find the matching ResourceDoc") + result should be(defined) + result.get.partialFunctionName should equal("getMetrics") + } + + scenario("Verb mismatch returns None", ResourceDocMatcherTag) { + Given("A ResourceDoc for GET /banks") + val resourceDocs = ArrayBuffer( + createResourceDoc("GET", "/banks", "getBanks") + ) + + When("Matching a POST request to /obp/v7.0.0/banks") + val path = Uri.Path.unsafeFromString("/obp/v7.0.0/banks") + val result = ResourceDocMatcher.findResourceDoc("POST", path, resourceDocs) + + Then("Should return None") + result should be(None) + } + + scenario("Path mismatch returns None", ResourceDocMatcherTag) { + Given("A ResourceDoc for GET /banks") + val resourceDocs = ArrayBuffer( + createResourceDoc("GET", "/banks", "getBanks") + ) + + When("Matching a GET request to /obp/v7.0.0/accounts") + val path = Uri.Path.unsafeFromString("/obp/v7.0.0/accounts") + val result = ResourceDocMatcher.findResourceDoc("GET", path, resourceDocs) + + Then("Should return None") + result should be(None) + } + } + + feature("ResourceDocMatcher - BANK_ID variable matching") { + + scenario("Match request with BANK_ID variable", ResourceDocMatcherTag) { + Given("A ResourceDoc for GET /banks/BANK_ID") + val resourceDocs = ArrayBuffer( + createResourceDoc("GET", "/banks/BANK_ID", "getBank") + ) + + When("Matching a GET request to /obp/v7.0.0/banks/gh.29.de") + val path = Uri.Path.unsafeFromString("/obp/v7.0.0/banks/gh.29.de") + val result = ResourceDocMatcher.findResourceDoc("GET", path, resourceDocs) + + Then("Should find the matching ResourceDoc") + result should be(defined) + result.get.partialFunctionName should equal("getBank") + } + + scenario("Match request with BANK_ID and additional segments", ResourceDocMatcherTag) { + Given("A ResourceDoc for GET /banks/BANK_ID/accounts") + val resourceDocs = ArrayBuffer( + createResourceDoc("GET", "/banks/BANK_ID/accounts", "getBankAccounts") + ) + + When("Matching a GET request to /obp/v7.0.0/banks/test-bank-1/accounts") + val path = Uri.Path.unsafeFromString("/obp/v7.0.0/banks/test-bank-1/accounts") + val result = ResourceDocMatcher.findResourceDoc("GET", path, resourceDocs) + + Then("Should find the matching ResourceDoc") + result should be(defined) + result.get.partialFunctionName should equal("getBankAccounts") + } + + scenario("Extract BANK_ID parameter value", ResourceDocMatcherTag) { + Given("A matched ResourceDoc with BANK_ID") + val resourceDoc = createResourceDoc("GET", "/banks/BANK_ID", "getBank") + + When("Extracting path parameters from /obp/v7.0.0/banks/gh.29.de") + val path = Uri.Path.unsafeFromString("/obp/v7.0.0/banks/gh.29.de") + val params = ResourceDocMatcher.extractPathParams(path, resourceDoc) + + Then("Should extract BANK_ID value") + params should contain key "BANK_ID" + params("BANK_ID") should equal("gh.29.de") + } + } + + feature("ResourceDocMatcher - BANK_ID + ACCOUNT_ID variables") { + + scenario("Match request with BANK_ID and ACCOUNT_ID variables", ResourceDocMatcherTag) { + Given("A ResourceDoc for GET /banks/BANK_ID/accounts/ACCOUNT_ID") + val resourceDocs = ArrayBuffer( + createResourceDoc("GET", "/banks/BANK_ID/accounts/ACCOUNT_ID", "getBankAccount") + ) + + When("Matching a GET request to /obp/v7.0.0/banks/gh.29.de/accounts/test1") + val path = Uri.Path.unsafeFromString("/obp/v7.0.0/banks/gh.29.de/accounts/test1") + val result = ResourceDocMatcher.findResourceDoc("GET", path, resourceDocs) + + Then("Should find the matching ResourceDoc") + result should be(defined) + result.get.partialFunctionName should equal("getBankAccount") + } + + scenario("Extract BANK_ID and ACCOUNT_ID parameter values", ResourceDocMatcherTag) { + Given("A matched ResourceDoc with BANK_ID and ACCOUNT_ID") + val resourceDoc = createResourceDoc("GET", "/banks/BANK_ID/accounts/ACCOUNT_ID", "getBankAccount") + + When("Extracting path parameters from /obp/v7.0.0/banks/gh.29.de/accounts/test1") + val path = Uri.Path.unsafeFromString("/obp/v7.0.0/banks/gh.29.de/accounts/test1") + val params = ResourceDocMatcher.extractPathParams(path, resourceDoc) + + Then("Should extract both BANK_ID and ACCOUNT_ID values") + params should contain key "BANK_ID" + params should contain key "ACCOUNT_ID" + params("BANK_ID") should equal("gh.29.de") + params("ACCOUNT_ID") should equal("test1") + } + + scenario("Match request with BANK_ID, ACCOUNT_ID and additional segments", ResourceDocMatcherTag) { + Given("A ResourceDoc for GET /banks/BANK_ID/accounts/ACCOUNT_ID/transactions") + val resourceDocs = ArrayBuffer( + createResourceDoc("GET", "/banks/BANK_ID/accounts/ACCOUNT_ID/transactions", "getTransactions") + ) + + When("Matching a GET request to /obp/v7.0.0/banks/test-bank/accounts/acc-123/transactions") + val path = Uri.Path.unsafeFromString("/obp/v7.0.0/banks/test-bank/accounts/acc-123/transactions") + val result = ResourceDocMatcher.findResourceDoc("GET", path, resourceDocs) + + Then("Should find the matching ResourceDoc") + result should be(defined) + result.get.partialFunctionName should equal("getTransactions") + } + } + + feature("ResourceDocMatcher - BANK_ID + ACCOUNT_ID + VIEW_ID variables") { + + scenario("Match request with BANK_ID, ACCOUNT_ID and VIEW_ID variables", ResourceDocMatcherTag) { + Given("A ResourceDoc for GET /banks/BANK_ID/accounts/ACCOUNT_ID/VIEW_ID/transactions") + val resourceDocs = ArrayBuffer( + createResourceDoc("GET", "/banks/BANK_ID/accounts/ACCOUNT_ID/VIEW_ID/transactions", "getTransactionsForView") + ) + + When("Matching a GET request to /obp/v7.0.0/banks/gh.29.de/accounts/test1/owner/transactions") + val path = Uri.Path.unsafeFromString("/obp/v7.0.0/banks/gh.29.de/accounts/test1/owner/transactions") + val result = ResourceDocMatcher.findResourceDoc("GET", path, resourceDocs) + + Then("Should find the matching ResourceDoc") + result should be(defined) + result.get.partialFunctionName should equal("getTransactionsForView") + } + + scenario("Extract BANK_ID, ACCOUNT_ID and VIEW_ID parameter values", ResourceDocMatcherTag) { + Given("A matched ResourceDoc with BANK_ID, ACCOUNT_ID and VIEW_ID") + val resourceDoc = createResourceDoc("GET", "/banks/BANK_ID/accounts/ACCOUNT_ID/VIEW_ID/transactions", "getTransactionsForView") + + When("Extracting path parameters from /obp/v7.0.0/banks/gh.29.de/accounts/test1/owner/transactions") + val path = Uri.Path.unsafeFromString("/obp/v7.0.0/banks/gh.29.de/accounts/test1/owner/transactions") + val params = ResourceDocMatcher.extractPathParams(path, resourceDoc) + + Then("Should extract all three parameter values") + params should contain key "BANK_ID" + params should contain key "ACCOUNT_ID" + params should contain key "VIEW_ID" + params("BANK_ID") should equal("gh.29.de") + params("ACCOUNT_ID") should equal("test1") + params("VIEW_ID") should equal("owner") + } + + scenario("Match request with VIEW_ID in different position", ResourceDocMatcherTag) { + Given("A ResourceDoc for GET /banks/BANK_ID/accounts/ACCOUNT_ID/VIEW_ID/account") + val resourceDocs = ArrayBuffer( + createResourceDoc("GET", "/banks/BANK_ID/accounts/ACCOUNT_ID/VIEW_ID/account", "getAccountForView") + ) + + When("Matching a GET request to /obp/v7.0.0/banks/test-bank/accounts/acc-1/public/account") + val path = Uri.Path.unsafeFromString("/obp/v7.0.0/banks/test-bank/accounts/acc-1/public/account") + val result = ResourceDocMatcher.findResourceDoc("GET", path, resourceDocs) + + Then("Should find the matching ResourceDoc") + result should be(defined) + result.get.partialFunctionName should equal("getAccountForView") + } + } + + feature("ResourceDocMatcher - COUNTERPARTY_ID variable") { + + scenario("Match request with COUNTERPARTY_ID variable", ResourceDocMatcherTag) { + Given("A ResourceDoc for GET /banks/BANK_ID/accounts/ACCOUNT_ID/VIEW_ID/counterparties/COUNTERPARTY_ID") + val resourceDocs = ArrayBuffer( + createResourceDoc("GET", "/banks/BANK_ID/accounts/ACCOUNT_ID/VIEW_ID/counterparties/COUNTERPARTY_ID", "getCounterparty") + ) + + When("Matching a GET request with counterparty ID") + val path = Uri.Path.unsafeFromString("/obp/v7.0.0/banks/gh.29.de/accounts/test1/owner/counterparties/ff010868-ac7d-4f96-9fc5-70dd5757e891") + val result = ResourceDocMatcher.findResourceDoc("GET", path, resourceDocs) + + Then("Should find the matching ResourceDoc") + result should be(defined) + result.get.partialFunctionName should equal("getCounterparty") + } + + scenario("Extract COUNTERPARTY_ID parameter value", ResourceDocMatcherTag) { + Given("A matched ResourceDoc with COUNTERPARTY_ID") + val resourceDoc = createResourceDoc("GET", "/banks/BANK_ID/accounts/ACCOUNT_ID/VIEW_ID/counterparties/COUNTERPARTY_ID", "getCounterparty") + + When("Extracting path parameters") + val path = Uri.Path.unsafeFromString("/obp/v7.0.0/banks/gh.29.de/accounts/test1/owner/counterparties/ff010868-ac7d-4f96-9fc5-70dd5757e891") + val params = ResourceDocMatcher.extractPathParams(path, resourceDoc) + + Then("Should extract all parameter values including COUNTERPARTY_ID") + params should contain key "BANK_ID" + params should contain key "ACCOUNT_ID" + params should contain key "VIEW_ID" + params should contain key "COUNTERPARTY_ID" + params("BANK_ID") should equal("gh.29.de") + params("ACCOUNT_ID") should equal("test1") + params("VIEW_ID") should equal("owner") + params("COUNTERPARTY_ID") should equal("ff010868-ac7d-4f96-9fc5-70dd5757e891") + } + + scenario("Match request with COUNTERPARTY_ID in different URL structure", ResourceDocMatcherTag) { + Given("A ResourceDoc for DELETE /management/counterparties/COUNTERPARTY_ID") + val resourceDocs = ArrayBuffer( + createResourceDoc("DELETE", "/management/counterparties/COUNTERPARTY_ID", "deleteCounterparty") + ) + + When("Matching a DELETE request") + val path = Uri.Path.unsafeFromString("/obp/v7.0.0/management/counterparties/counterparty-123") + val result = ResourceDocMatcher.findResourceDoc("DELETE", path, resourceDocs) + + Then("Should find the matching ResourceDoc") + result should be(defined) + result.get.partialFunctionName should equal("deleteCounterparty") + } + } + + feature("ResourceDocMatcher - Non-matching requests") { + + scenario("Return None when no ResourceDoc matches", ResourceDocMatcherTag) { + Given("ResourceDocs for specific endpoints") + val resourceDocs = ArrayBuffer( + createResourceDoc("GET", "/banks", "getBanks"), + createResourceDoc("GET", "/banks/BANK_ID", "getBank"), + createResourceDoc("POST", "/banks", "createBank") + ) + + When("Matching a request that doesn't match any ResourceDoc") + val path = Uri.Path.unsafeFromString("/obp/v7.0.0/accounts") + val result = ResourceDocMatcher.findResourceDoc("GET", path, resourceDocs) + + Then("Should return None") + result should be(None) + } + + scenario("Return None when verb doesn't match", ResourceDocMatcherTag) { + Given("A ResourceDoc for GET /banks") + val resourceDocs = ArrayBuffer( + createResourceDoc("GET", "/banks", "getBanks") + ) + + When("Matching a DELETE request to /obp/v7.0.0/banks") + val path = Uri.Path.unsafeFromString("/obp/v7.0.0/banks") + val result = ResourceDocMatcher.findResourceDoc("DELETE", path, resourceDocs) + + Then("Should return None") + result should be(None) + } + + scenario("Return None when path segment count doesn't match", ResourceDocMatcherTag) { + Given("A ResourceDoc for GET /banks/BANK_ID/accounts") + val resourceDocs = ArrayBuffer( + createResourceDoc("GET", "/banks/BANK_ID/accounts", "getBankAccounts") + ) + + When("Matching a request with different segment count") + val path = Uri.Path.unsafeFromString("/obp/v7.0.0/banks/gh.29.de") + val result = ResourceDocMatcher.findResourceDoc("GET", path, resourceDocs) + + Then("Should return None") + result should be(None) + } + + scenario("Return None when literal segments don't match", ResourceDocMatcherTag) { + Given("A ResourceDoc for GET /banks/BANK_ID/accounts") + val resourceDocs = ArrayBuffer( + createResourceDoc("GET", "/banks/BANK_ID/accounts", "getBankAccounts") + ) + + When("Matching a request with different literal segment") + val path = Uri.Path.unsafeFromString("/obp/v7.0.0/banks/gh.29.de/transactions") + val result = ResourceDocMatcher.findResourceDoc("GET", path, resourceDocs) + + Then("Should return None") + result should be(None) + } + } + + feature("ResourceDocMatcher - Path parameter extraction edge cases") { + + scenario("Extract parameters from path with no variables", ResourceDocMatcherTag) { + Given("A ResourceDoc with no path variables") + val resourceDoc = createResourceDoc("GET", "/banks", "getBanks") + + When("Extracting path parameters") + val path = Uri.Path.unsafeFromString("/obp/v7.0.0/banks") + val params = ResourceDocMatcher.extractPathParams(path, resourceDoc) + + Then("Should return empty map") + params should be(empty) + } + + scenario("Extract parameters with special characters in values", ResourceDocMatcherTag) { + Given("A ResourceDoc with BANK_ID") + val resourceDoc = createResourceDoc("GET", "/banks/BANK_ID", "getBank") + + When("Extracting path parameters with special characters") + val path = Uri.Path.unsafeFromString("/obp/v7.0.0/banks/gh.29.de-test_bank") + val params = ResourceDocMatcher.extractPathParams(path, resourceDoc) + + Then("Should extract the full value including special characters") + params should contain key "BANK_ID" + params("BANK_ID") should equal("gh.29.de-test_bank") + } + + scenario("Return empty map when path doesn't match template", ResourceDocMatcherTag) { + Given("A ResourceDoc for /banks/BANK_ID") + val resourceDoc = createResourceDoc("GET", "/banks/BANK_ID", "getBank") + + When("Extracting parameters from path with different segment count") + val path = Uri.Path.unsafeFromString("/obp/v7.0.0/accounts") + val params = ResourceDocMatcher.extractPathParams(path, resourceDoc) + + Then("Should return empty map due to segment count mismatch") + params should be(empty) + } + } + + feature("ResourceDocMatcher - attachToCallContext") { + + scenario("Attach ResourceDoc to CallContext", ResourceDocMatcherTag) { + Given("A CallContext and a matched ResourceDoc") + val resourceDoc = createResourceDoc("GET", "/banks", "getBanks") + val callContext = code.api.util.CallContext( + correlationId = "test-correlation-id" + ) + + When("Attaching ResourceDoc to CallContext") + val updatedContext = ResourceDocMatcher.attachToCallContext(callContext, resourceDoc) + + Then("CallContext should have resourceDocument set") + updatedContext.resourceDocument should be(defined) + updatedContext.resourceDocument.get should equal(resourceDoc) + } + + scenario("Attach ResourceDoc sets operationId", ResourceDocMatcherTag) { + Given("A CallContext and a matched ResourceDoc") + val resourceDoc = createResourceDoc("GET", "/banks/BANK_ID", "getBank") + val callContext = code.api.util.CallContext( + correlationId = "test-correlation-id" + ) + + When("Attaching ResourceDoc to CallContext") + val updatedContext = ResourceDocMatcher.attachToCallContext(callContext, resourceDoc) + + Then("CallContext should have operationId set") + updatedContext.operationId should be(defined) + updatedContext.operationId.get should equal(resourceDoc.operationId) + } + + scenario("Preserve other CallContext fields when attaching ResourceDoc", ResourceDocMatcherTag) { + Given("A CallContext with existing fields") + val resourceDoc = createResourceDoc("GET", "/banks", "getBanks") + val originalContext = code.api.util.CallContext( + correlationId = "test-correlation-id", + url = "/obp/v7.0.0/banks", + verb = "GET", + implementedInVersion = "v7.0.0" + ) + + When("Attaching ResourceDoc to CallContext") + val updatedContext = ResourceDocMatcher.attachToCallContext(originalContext, resourceDoc) + + Then("Other fields should be preserved") + updatedContext.correlationId should equal(originalContext.correlationId) + updatedContext.url should equal(originalContext.url) + updatedContext.verb should equal(originalContext.verb) + updatedContext.implementedInVersion should equal(originalContext.implementedInVersion) + } + } + + feature("ResourceDocMatcher - Multiple ResourceDocs selection") { + + scenario("Select correct ResourceDoc from multiple candidates", ResourceDocMatcherTag) { + Given("Multiple ResourceDocs with different paths") + val resourceDocs = ArrayBuffer( + createResourceDoc("GET", "/banks", "getBanks"), + createResourceDoc("GET", "/banks/BANK_ID", "getBank"), + createResourceDoc("GET", "/banks/BANK_ID/accounts", "getBankAccounts"), + createResourceDoc("POST", "/banks", "createBank") + ) + + When("Matching a specific request") + val path = Uri.Path.unsafeFromString("/obp/v7.0.0/banks/gh.29.de/accounts") + val result = ResourceDocMatcher.findResourceDoc("GET", path, resourceDocs) + + Then("Should select the most specific matching ResourceDoc") + result should be(defined) + result.get.partialFunctionName should equal("getBankAccounts") + } + + scenario("Match first ResourceDoc when multiple exact matches exist", ResourceDocMatcherTag) { + Given("Multiple ResourceDocs with same path and verb") + val resourceDocs = ArrayBuffer( + createResourceDoc("GET", "/banks", "getBanks1"), + createResourceDoc("GET", "/banks", "getBanks2") + ) + + When("Matching a request") + val path = Uri.Path.unsafeFromString("/obp/v7.0.0/banks") + val result = ResourceDocMatcher.findResourceDoc("GET", path, resourceDocs) + + Then("Should return the first matching ResourceDoc") + result should be(defined) + result.get.partialFunctionName should equal("getBanks1") + } + } + + feature("ResourceDocMatcher - Case sensitivity") { + + scenario("HTTP verb matching is case-insensitive", ResourceDocMatcherTag) { + Given("A ResourceDoc with uppercase GET") + val resourceDocs = ArrayBuffer( + createResourceDoc("GET", "/banks", "getBanks") + ) + + When("Matching with lowercase get") + val path = Uri.Path.unsafeFromString("/obp/v7.0.0/banks") + val result = ResourceDocMatcher.findResourceDoc("get", path, resourceDocs) + + Then("Should find the matching ResourceDoc") + result should be(defined) + result.get.partialFunctionName should equal("getBanks") + } + + scenario("Path matching is case-sensitive for literal segments", ResourceDocMatcherTag) { + Given("A ResourceDoc for /banks") + val resourceDocs = ArrayBuffer( + createResourceDoc("GET", "/banks", "getBanks") + ) + + When("Matching with different case /Banks") + val path = Uri.Path.unsafeFromString("/obp/v7.0.0/Banks") + val result = ResourceDocMatcher.findResourceDoc("GET", path, resourceDocs) + + Then("Should not match (case-sensitive)") + result should be(None) + } + } +}