diff --git a/README.md b/README.md index 4c6ca45..13cbe9b 100644 --- a/README.md +++ b/README.md @@ -183,7 +183,7 @@ public function main() returns error? { ## Examples -The `HubSpot Marketing Campaigns ` connector provides practical examples illustrating usage in various scenarios. Explore these [examples](https://github.com/SamudraUduwaka/module-ballerinax-hubspot.marketing.campaigns/tree/b1251412885d8b083c0df636bfeb85bebc4aeff3/examples), covering the following use cases: +The `HubSpot Marketing Campaigns ` connector provides practical examples illustrating usage in various scenarios. Explore these [examples](https://github.com/ballerina-platform/module-ballerinax-hubspot.marketing.campaigns/tree/main/examples), covering the following use cases: ## Build from the source diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index b385d49..dfc60af 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -98,6 +98,9 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} ] +modules = [ + {org = "ballerina", packageName = "io", moduleName = "io"} +] [[package]] org = "ballerina" @@ -320,6 +323,7 @@ name = "hubspot.marketing.campaigns" version = "1.0.0" dependencies = [ {org = "ballerina", name = "http"}, + {org = "ballerina", name = "io"}, {org = "ballerina", name = "oauth2"}, {org = "ballerina", name = "test"}, {org = "ballerina", name = "time"}, diff --git a/ballerina/Package.md b/ballerina/Package.md index 2f83466..85792cd 100644 --- a/ballerina/Package.md +++ b/ballerina/Package.md @@ -2,7 +2,7 @@ [HubSpot](https://www.hubspot.com/our-story) is an AI-powered customer relationship management (CRM) platform. -The ballerinax/module-ballerinax-hubspot.marketing.campaigns offers APIs to connect and interact with the [Hubspot Marketing Campaings API](https://github.com/HubSpot/HubSpot-public-api-spec-collection/blob/main/PublicApiSpecs/Marketing/Campaigns%20Public%20Api/Rollouts/177944/v3/campaignsPublicApi.json) endpoints, specifically based on the [Hubspot Marketing Campaings API Documentation](https://developers.hubspot.com/docs/reference/api/marketing/campaigns) +The `ballerinax/module-ballerinax-hubspot.marketing.campaigns` connector offers APIs to connect and interact with the [Hubspot Marketing Campaigns API](https://developers.hubspot.com/docs/guides/api/marketing/campaigns) endpoints, specifically based on the [HubSpot REST API](https://developers.hubspot.com/docs/reference/api/overview) ## Setup guide @@ -172,7 +172,7 @@ public function main() returns error? { } ``` -## Examples -The `HubSpot Marketing Campaigns ` connector provides practical examples illustrating usage in various scenarios. Explore these [examples](https://github.com/module-ballerinax-hubspot.marketing.campaigns/tree/main/examples/), covering the following use cases: +## Examples +The `HubSpot Marketing Campaigns ` connector provides practical examples illustrating usage in various scenarios. Explore these [examples](https://github.com/ballerina-platform/module-ballerinax-hubspot.marketing.campaigns/tree/main/examples), covering the following use cases: \ No newline at end of file diff --git a/ballerina/tests/mock_service.bal b/ballerina/tests/mock_service.bal new file mode 100644 index 0000000..7ba83ad --- /dev/null +++ b/ballerina/tests/mock_service.bal @@ -0,0 +1,35 @@ + +// import ballerina/http; +// import ballerina/log; + +// listener http:Listener httpListener = new(9091); + +// http:Service mockService = service object{ +// resource function get marketing/v3/marketing/[string mockId]() returns CollectionResponsePublicCampaignAssetForwardPaging{ +// return { +// results: { +// "id": mockId, +// "properties": {}, +// "createdAt": "2025-01-07T04:45:53.011Z", +// "updatedAt": "2025-01-08T09:52:24.054Z", +// "assets": { +// "FORM": { +// "results": [ +// { +// "id": "88047023-7777-40a1-b74b-4b1139e8d45b", +// "name": "New form (January 3, 2025 4:37:41 AM EST)" +// } +// ] +// } +// } +// } + +// } +// } +// } + +// function init() returns error?{ +// log:printInfo("Initializing mock service"); +// check httpListener.attach(mockService, "/"); +// check httpListener.'start(); +// } \ No newline at end of file diff --git a/ballerina/tests/README.md b/ballerina/tests/mock_test.bal similarity index 100% rename from ballerina/tests/README.md rename to ballerina/tests/mock_test.bal diff --git a/ballerina/tests/test.bal b/ballerina/tests/test.bal index 7ad289a..fb6648f 100644 --- a/ballerina/tests/test.bal +++ b/ballerina/tests/test.bal @@ -33,135 +33,178 @@ OAuth2RefreshTokenGrantConfig authConfig = { ConnectionConfig config = {auth: authConfig}; -final Client baseClient = check new Client(config); +final Client baseClient = check new (config); -//Variables -string campaignGuid2 = "" ; +string campaignGuid2 = ""; configurable string campaignGuid = ?; configurable string assetType = ?; configurable string assetID = ?; +configurable string sampleCampaignGuid1 = ?; +configurable string sampleCampaignGuid2 = ?; +configurable string sampleCampaignGuid3 = ?; +configurable string sampleCampaignGuid4 = ?; + + +//SearchMarketingCampaigns @test:Config {} isolated function testGetSearchMarketingCampaigns() returns error? { CollectionResponseWithTotalPublicCampaignForwardPaging response = check baseClient->/.get(); test:assertTrue(response?.results.length() > 0); } +//CreateMarketingCampaigns @test:Config {} function testPostCreateMarketingCampaigns() returns error? { PublicCampaign response = check baseClient->/.post( - payload = {properties: { - "hs_name": "campaign" + time:utcNow().toString() , - "hs_goal": "campaignGoalSpecified", - "hs_notes": "someNotesForTheCampaign" - }} + payload = { + properties: { + "hs_name": "campaign" + time:utcNow().toString(), + "hs_goal": "campaignGoalSpecified", + "hs_notes": "someNotesForTheCampaign" + } + } ); - test:assertTrue(response?.id != ""); + test:assertNotEquals(response?.id , ""); campaignGuid2 = response?.id; } +//Read a Marketing Campaign @test:Config {} isolated function testGetReadACampaign() returns error? { PublicCampaignWithAssets response = check baseClient->/[campaignGuid]; - test:assertTrue(response?.id == campaignGuid); + test:assertEquals(response?.id , campaignGuid); } +//Update a Marketing Campaign @test:Config {} isolated function testPatchUpdateCampaigns() returns error? { PublicCampaign response = check baseClient->/[campaignGuid].patch( - payload = {properties: { - "hs_goal": "updatedCampaignGoal", - "hs_notes": "updatedNotesForTheCampaign" - }} + payload = { + properties: { + "hs_goal": "updatedCampaignGoal", + "hs_notes": "updatedNotesForTheCampaign" + } + } ); - test:assertTrue(response?.id == campaignGuid); + test:assertEquals(response?.id , campaignGuid); } +//Create a Batch of Marketing Campaigns @test:Config {} isolated function testPostBatchCreate() returns error? { BatchResponsePublicCampaign|BatchResponsePublicCampaignWithErrors response = check baseClient->/batch/create.post( payload = { - "inputs": [ - { - "properties": { - "hs_name": "batchCampaign" + time:utcToString(time:utcNow()), - "hs_goal": "batchCampaignGoalSpecified" - } + "inputs": [ + { + "properties": { + "hs_name": "batchCampaign" + time:utcToString(time:utcNow()), + "hs_goal": "batchCampaignGoalSpecified" } - ] - } + } + ] + } ); - test:assertTrue(response?.status == "COMPLETE"); + test:assertEquals(response?.status , "COMPLETE"); } +//Update a Batch of Marketing Campaigns @test:Config {} -isolated function testPostBatchRead() returns error? { - BatchResponsePublicCampaignWithAssets|BatchResponsePublicCampaignWithAssetsWithErrors response = check baseClient->/batch/read.post( +isolated function testPostBatchUpdate() returns error? { + BatchResponsePublicCampaign|BatchResponsePublicCampaignWithErrors response = check baseClient->/batch/update.post( payload = { - "inputs": [ - { - "id": "ef46bced-1a75-42b5-9f5f-ebdd39cbfd3b" + "inputs": [ + { + "id": sampleCampaignGuid1, + "properties": { + "hs_goal": "updatedGoal", + "hs_notes": "updatedNote" } - ] - } + } + ] + } + ); + test:assertEquals(response?.status , "COMPLETE"); +} + +//Read a Batch of Marketing Campaigns +@test:Config {} +isolated function testPostBatchRead() returns error? { + BatchResponsePublicCampaignWithAssets|BatchResponsePublicCampaignWithAssetsWithErrors response = check baseClient->/batch/read.post( + payload = { + "inputs": [ + { + "id": sampleCampaignGuid2 + } + ] + } ); - test:assertTrue(response?.status == "COMPLETE"); + test:assertEquals(response?.status , "COMPLETE"); } +//Get Reports - Revenue @test:Config {} isolated function testGetReportsRevenue() returns error? { RevenueAttributionAggregate response = check baseClient->/[campaignGuid]/reports/revenue; test:assertTrue(response?.revenueAmount is decimal); } +//Reports Metrics @test:Config {} isolated function testGetReportsMetrics() returns error? { MetricsCounters response = check baseClient->/[campaignGuid]/reports/metrics; - test:assertTrue(response?.sessions == 0); + test:assertTrue(response?.sessions >= 0); } +//List Assets Associated with a Campaign @test:Config {} -isolated function testGetListAssets() returns error? { +isolated function testGetListAssets() returns error? { CollectionResponsePublicCampaignAssetForwardPaging response = check baseClient->/[campaignGuid]/assets/[assetType]; test:assertTrue(response?.results.length() > 0); - + } -@test:Config {} -isolated function testPutAddAssetAssociation() returns error? { +//Add an Asset Association to a Campaign +@test:Config { + dependsOn: [testDeleteRemoveAssetAssociation] +} +isolated function testPutAddAssetAssociation() returns error? { var response = check baseClient->/[campaignGuid]/assets/[assetType]/[assetID].put(); - test:assertTrue(response.statusCode == 204); + test:assertEquals(response.statusCode , 204); } +//Remove an Asset Association from a Campaign @test:Config { - dependsOn: [testPutAddAssetAssociation, testGetListAssets] + dependsOn: [testGetListAssets] } -isolated function testDeleteRemoveAssetAssociation() returns error? { +isolated function testDeleteRemoveAssetAssociation() returns error? { var response = check baseClient->/[campaignGuid]/assets/[assetType]/[assetID].delete(); - test:assertTrue(response.statusCode == 204); + test:assertEquals(response.statusCode , 204); } +//Delete a Marketing Campaign @test:Config { dependsOn: [testPostCreateMarketingCampaigns] } -function testDeleteCampaign() returns error? { +function testDeleteCampaign() returns error? { var response = check baseClient->/[campaignGuid2].delete(); - test:assertTrue(response.statusCode == 204); + test:assertEquals(response.statusCode , 204); } +//Delete a Batch of Marketing Campaigns @test:Config {} isolated function testPostDeleteABatchOfCampaigns() returns error? { var response = check baseClient->/batch/archive.post( payload = { "inputs": [ { - "id": "b3e493b0-9d5a-4b3e-a362-f4e0f015345d" + "id": sampleCampaignGuid3 }, { - "id": "96a87dab-554a-474c-853b-c78193a8b889" + "id": sampleCampaignGuid4 } ] } ); - test:assertTrue(response.statusCode == 204); + test:assertEquals(response.statusCode , 204); } diff --git a/build-config/resources/Ballerina.toml b/build-config/resources/Ballerina.toml index 8e47a35..c2310ae 100644 --- a/build-config/resources/Ballerina.toml +++ b/build-config/resources/Ballerina.toml @@ -5,7 +5,7 @@ name = "hubspot.marketing.campaigns" version = "1.0.0" license = ["Apache-2.0"] authors = ["Ballerina"] -keywords = [] # TODO: Add keywords +keywords = ["hubspot", "crm", "marketing", "campaigns"] # icon = "icon.png" # TODO: Add icon repository = "https://github.com/ballerina-platform/module-ballerinax-hubspot.marketing.campaigns"