-
Couldn't load subscription status.
- Fork 1
Feature – Contact Events API (Issue #151) #152
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
Conversation
- Added Contact Events management interfaces, models, requests, and validation - Added example project to demonstrate Contact Events API usage - Updated Contacts interface to provide access to Contact Events - Added Contact Events unit tests and integration tests - Extended Contacts unit tests to cover new methods for accessing events
WalkthroughAdds Contact Events feature: new abstractions (model, request, validator, interface), concrete resource and navigation from contacts, example console project, global usings, solution wiring, and comprehensive unit/integration tests with JSON fixtures. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant App as Example App
participant Client as IMailtrapClient
participant Accounts as Accounts Resource
participant Contacts as Contacts Resource
participant Events as ContactsEventCollectionResource
participant API as Mailtrap API
App->>Client: Resolve from DI
App->>Accounts: client.Accounts(accountId)
Accounts->>Contacts: .Contacts()
Contacts->>Events: .Events(contactId)
App->>Events: Create(request)
Events->>API: POST /accounts/{id}/contacts/{contactId}/events
API-->>Events: 201 Created (ContactsEvent)
Events-->>App: ContactsEvent
App->>App: Log event details
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests
Tip 👮 Agentic pre-merge checks are now available in preview!Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.
Please see the documentation for more information. Example: reviews:
pre_merge_checks:
custom_checks:
- name: "Undocumented Breaking Changes"
mode: "warning"
instructions: |
Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).Please share your feedback with us on this Discord post. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
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.
Actionable comments posted: 4
🧹 Nitpick comments (11)
examples/Mailtrap.Example.ContactEvents/appsettings.json (1)
1-17: Avoid secrets in repo; prefer env vars or user‑secretsKeep the placeholder, and document using Mailtrap__ApiToken env var or dotnet user‑secrets to supply the token at run time.
src/Mailtrap.Abstractions/ContactEvents/IContactsEventsCollectionResource.cs (1)
1-1: Rename file to match type name.File is
IContactsEventsCollectionResource.csbut type isIContactsEventCollectionResource. Please align.examples/Mailtrap.Example.ContactEvents/Program.cs (3)
29-31: Use configuration for accountId instead of a magic number.Improves portability of the example.
Apply:
- var accountId = 12345; + var accountId = hostBuilder.Configuration.GetSection("Mailtrap").GetValue<long?>("AccountId") ?? 12345;
56-56: Nullability warning: contact may be considered nullable by the compiler.Make the intent explicit to avoid CS8602.
Apply:
- IContactsEventCollectionResource contactsEventsResource = contactsResource.Events(contact.Id); + IContactsEventCollectionResource contactsEventsResource = contactsResource.Events(contact!.Id);
64-64: Log message label is incorrect.“Created At” doesn’t match the logged value (ContactEmail).
Apply:
- logger.LogInformation("Created At: {ContactEmail}", contactsEvent.ContactEmail); + logger.LogInformation("Contact Email: {ContactEmail}", contactsEvent.ContactEmail);src/Mailtrap.Abstractions/ContactEvents/Validators/CreateContactsEventRequestValidator.cs (1)
23-31: Simplify key validation with RuleForEach; current ChildRules usage is unnecessary.This is clearer and aligns with typical FluentValidation patterns.
Apply:
- When(r => r.Params != null && r.Params.Count > 0, () => - { - RuleFor(r => r.Params.Keys) - .Cascade(CascadeMode.Stop) - .ChildRules(r => - { - r.RuleForEach(k => k).NotEmpty().MaximumLength(255); - }); - }); + When(r => r.Params != null && r.Params.Count > 0, () => + { + RuleForEach(r => r.Params.Keys) + .Cascade(CascadeMode.Stop) + .NotEmpty() + .MaximumLength(255); + });tests/Mailtrap.UnitTests/ContactEvents/Requests/CreateContactsEventRequestTests.cs (1)
27-45: Add a test to assert defensive copy semantics for Params.Ensure later mutations of the source dictionary don’t affect the request state.
Add:
@@ public void Constructor_ShouldInitializeFieldsCorrectly() { @@ request.Params.Should().BeEquivalentTo(parameters); } + + [Test] + public void Constructor_ShouldDefensivelyCopyParams() + { + // Arrange + var src = new Dictionary<string, object?> { { "k", "v" } }; + var request = new CreateContactsEventRequest("name", src); + + // Act + src["k"] = "changed"; + src["new"] = 123; + + // Assert + request.Params.Should().BeEquivalentTo(new Dictionary<string, object?> { { "k", "v" } }); + }src/Mailtrap.Abstractions/ContactEvents/Requests/CreateContactsEventRequest.cs (1)
15-18: Minor: default-initialize Name at the property for consistency.Keeps defaults visible in one place; behavior unchanged.
Apply:
- public string Name { get; set; } + public string Name { get; set; } = string.Empty;And simplify the parameterless ctor:
- [JsonConstructor] - public CreateContactsEventRequest() - { - Name = string.Empty; - } + [JsonConstructor] + public CreateContactsEventRequest() { }tests/Mailtrap.IntegrationTests/ContactEvents/ContactsEventsIntegrationTests.cs (3)
45-51: Silence nullable warnings for deserialization results.Use the null‑forgiving operator so the compiler knows these aren’t null after assertions.
- var request = JsonSerializer.Deserialize<CreateContactsEventRequest>(requestContent, _jsonSerializerOptions); - request.Should().NotBeNull(); + var request = JsonSerializer.Deserialize<CreateContactsEventRequest>(requestContent, _jsonSerializerOptions)!; + request.Should().NotBeNull(); - var expectedResponse = await responseContent.DeserializeStringContentAsync<ContactsEvent>(_jsonSerializerOptions); - expectedResponse.Should().NotBeNull(); + var expectedResponse = (await responseContent.DeserializeStringContentAsync<ContactsEvent>(_jsonSerializerOptions))!; + expectedResponse.Should().NotBeNull();- var request = JsonSerializer.Deserialize<CreateContactsEventRequest>(requestContent, _jsonSerializerOptions); - request.Should().NotBeNull(); + var request = JsonSerializer.Deserialize<CreateContactsEventRequest>(requestContent, _jsonSerializerOptions)!; + request.Should().NotBeNull(); - var expectedResponse = await responseContent.DeserializeStringContentAsync<ContactsEvent>(_jsonSerializerOptions); - expectedResponse.Should().NotBeNull(); + var expectedResponse = (await responseContent.DeserializeStringContentAsync<ContactsEvent>(_jsonSerializerOptions))!; + expectedResponse.Should().NotBeNull();Also applies to: 95-101
39-83: DRY the duplicated Arrange/Act in success tests.Both success tests are identical aside from fixtures. Extract a helper to reduce duplication and speed up future edits.
[Test] public async Task Create_WithParams_Success() { - // Arrange - var httpMethod = HttpMethod.Post; - var requestUri = _resourceUri.AbsoluteUri; - ... - result.ShouldBeEquivalentToContactResponse(expectedResponse); + await RunCreateSuccessAsync(); } @@ [Test] public async Task Create_Plain_Success() { - // Arrange - var httpMethod = HttpMethod.Post; - var requestUri = _resourceUri.AbsoluteUri; - ... - result.ShouldBeEquivalentToContactResponse(expectedResponse); + await RunCreateSuccessAsync(); }Add this helper inside the class:
private async Task RunCreateSuccessAsync() { var httpMethod = HttpMethod.Post; var requestUri = _resourceUri.AbsoluteUri; var fileName = TestContext.CurrentContext.Test.MethodName; var requestContent = await Feature.LoadFileToString(fileName + "_Request"); var request = JsonSerializer.Deserialize<CreateContactsEventRequest>(requestContent, _jsonSerializerOptions)!; request.Should().NotBeNull(); using var responseContent = await Feature.LoadFileToStringContent(fileName + "_Response"); var expectedResponse = (await responseContent.DeserializeStringContentAsync<ContactsEvent>(_jsonSerializerOptions))!; expectedResponse.Should().NotBeNull(); using var mockHttp = new MockHttpMessageHandler(); mockHttp.Expect(httpMethod, requestUri) .WithHeaders("Authorization", $"Bearer {_clientConfig.ApiToken}") .WithHeaders("Accept", MimeTypes.Application.Json) .WithHeaders("User-Agent", HeaderValues.UserAgent.ToString()) .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.Created, responseContent); var services = new ServiceCollection() .AddMailtrapClient(_clientConfig) .ConfigurePrimaryHttpMessageHandler(() => mockHttp) .BuildServiceProvider(); using (services as IDisposable) { var client = services.GetRequiredService<IMailtrapClient>(); var result = await client.Account(_accountId).Contacts().Events(_contactId).Create(request).ConfigureAwait(false); mockHttp.VerifyNoOutstandingExpectation(); result.ShouldBeEquivalentToContactResponse(expectedResponse); } }Also applies to: 88-131
5-5: Class/file naming mismatch.File is ContactsEventsIntegrationTests.cs, class is ContactsEventIntegrationTests. Align names for discoverability.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (26)
Mailtrap.sln(3 hunks)examples/Mailtrap.Example.ContactEvents/Mailtrap.Example.ContactEvents.csproj(1 hunks)examples/Mailtrap.Example.ContactEvents/Program.cs(1 hunks)examples/Mailtrap.Example.ContactEvents/Properties/launchSettings.json(1 hunks)examples/Mailtrap.Example.ContactEvents/appsettings.json(1 hunks)src/Mailtrap.Abstractions/ContactEvents/IContactsEventsCollectionResource.cs(1 hunks)src/Mailtrap.Abstractions/ContactEvents/Models/ContactsEvent.cs(1 hunks)src/Mailtrap.Abstractions/ContactEvents/Requests/CreateContactsEventRequest.cs(1 hunks)src/Mailtrap.Abstractions/ContactEvents/Validators/CreateContactsEventRequestValidator.cs(1 hunks)src/Mailtrap.Abstractions/Contacts/IContactCollectionResource.cs(1 hunks)src/Mailtrap.Abstractions/GlobalUsings.cs(1 hunks)src/Mailtrap/ContactEvents/ContactsEventCollectionResource.cs(1 hunks)src/Mailtrap/Contacts/ContactCollectionResource.cs(2 hunks)src/Mailtrap/GlobalUsings.cs(1 hunks)tests/Mailtrap.IntegrationTests/ContactEvents/ContactsEventsIntegrationTests.cs(1 hunks)tests/Mailtrap.IntegrationTests/ContactEvents/Create_Plain_Success_Request.json(1 hunks)tests/Mailtrap.IntegrationTests/ContactEvents/Create_Plain_Success_Response.json(1 hunks)tests/Mailtrap.IntegrationTests/ContactEvents/Create_WithParams_Success_Request.json(1 hunks)tests/Mailtrap.IntegrationTests/ContactEvents/Create_WithParams_Success_Response.json(1 hunks)tests/Mailtrap.IntegrationTests/GlobalUsings.cs(1 hunks)tests/Mailtrap.IntegrationTests/TestConstants/UrlSegmentsTestConstants.cs(1 hunks)tests/Mailtrap.UnitTests/ContactEvents/ContactsEventCollectionResourceTests.cs(1 hunks)tests/Mailtrap.UnitTests/ContactEvents/Requests/CreateContactsEventRequestTests.cs(1 hunks)tests/Mailtrap.UnitTests/Contacts/ContactCollectionResourceTests.cs(1 hunks)tests/Mailtrap.UnitTests/GlobalUsings.cs(1 hunks)tests/Mailtrap.UnitTests/TestConstants/UrlSegmentsTestConstants.cs(1 hunks)
🧰 Additional context used
🧠 Learnings (7)
📚 Learning: 2025-09-22T08:20:57.349Z
Learnt from: dr-3lo
PR: railsware/mailtrap-dotnet#150
File: src/Mailtrap.Abstractions/ContactFields/Validators/CreateContactsFieldRequestValidator.cs:8-8
Timestamp: 2025-09-22T08:20:57.349Z
Learning: In the Mailtrap.Abstractions project, global using statements in GlobalUsings.cs make types from Mailtrap.ContactFields.Requests (and other ContactFields namespaces) globally available, so explicit using statements are not needed in individual files like validators.
Applied to files:
tests/Mailtrap.UnitTests/GlobalUsings.cssrc/Mailtrap/GlobalUsings.cssrc/Mailtrap.Abstractions/GlobalUsings.cssrc/Mailtrap.Abstractions/ContactEvents/Validators/CreateContactsEventRequestValidator.csexamples/Mailtrap.Example.ContactEvents/Program.csexamples/Mailtrap.Example.ContactEvents/Mailtrap.Example.ContactEvents.csprojtests/Mailtrap.IntegrationTests/GlobalUsings.csMailtrap.sln
📚 Learning: 2025-09-22T08:20:27.713Z
Learnt from: dr-3lo
PR: railsware/mailtrap-dotnet#150
File: src/Mailtrap.Abstractions/ContactFields/Validators/CreateContactsFieldRequestValidator.cs:1-1
Timestamp: 2025-09-22T08:20:27.713Z
Learning: In the Mailtrap .NET project, FluentValidation is imported globally through GlobalUsings.cs files, making explicit using statements for FluentValidation unnecessary in individual validator files within the project.
Applied to files:
tests/Mailtrap.UnitTests/GlobalUsings.cssrc/Mailtrap/GlobalUsings.cssrc/Mailtrap.Abstractions/GlobalUsings.cstests/Mailtrap.IntegrationTests/GlobalUsings.cs
📚 Learning: 2025-09-22T09:52:44.028Z
Learnt from: dr-3lo
PR: railsware/mailtrap-dotnet#150
File: examples/Mailtrap.Example.ContactFields/Mailtrap.Example.ContactFields.csproj:1-10
Timestamp: 2025-09-22T09:52:44.028Z
Learning: In the Mailtrap .NET client project, example projects use a centralized `mailtrap-example.props` file to define common MSBuild properties like TargetFramework, so individual .csproj files don't need to explicitly declare these properties.
Applied to files:
tests/Mailtrap.UnitTests/GlobalUsings.csexamples/Mailtrap.Example.ContactEvents/Properties/launchSettings.jsonsrc/Mailtrap/GlobalUsings.cssrc/Mailtrap.Abstractions/GlobalUsings.csexamples/Mailtrap.Example.ContactEvents/Program.csexamples/Mailtrap.Example.ContactEvents/Mailtrap.Example.ContactEvents.csprojexamples/Mailtrap.Example.ContactEvents/appsettings.jsontests/Mailtrap.IntegrationTests/GlobalUsings.csMailtrap.sln
📚 Learning: 2025-09-04T12:22:07.783Z
Learnt from: dr-3lo
PR: railsware/mailtrap-dotnet#139
File: src/Mailtrap/Contacts/Requests/ContactRequestExtensions.cs:6-9
Timestamp: 2025-09-04T12:22:07.783Z
Learning: In the Mailtrap .NET client codebase, internal extension methods with non-nullable reference types don't require explicit null guards as the compiler provides compile-time safety and call sites are controlled within the codebase.
Applied to files:
tests/Mailtrap.UnitTests/GlobalUsings.cssrc/Mailtrap/GlobalUsings.cssrc/Mailtrap.Abstractions/GlobalUsings.csexamples/Mailtrap.Example.ContactEvents/Program.cstests/Mailtrap.IntegrationTests/GlobalUsings.cs
📚 Learning: 2025-09-04T12:23:59.276Z
Learnt from: dr-3lo
PR: railsware/mailtrap-dotnet#139
File: tests/Mailtrap.IntegrationTests/Contacts/Update_Success.json:16-17
Timestamp: 2025-09-04T12:23:59.276Z
Learning: Test fixtures in the Mailtrap .NET client should accurately represent the actual server response format and should not be modified to match client-side converters or serialization preferences.
Applied to files:
tests/Mailtrap.IntegrationTests/ContactEvents/Create_WithParams_Success_Response.jsonexamples/Mailtrap.Example.ContactEvents/Program.cstests/Mailtrap.IntegrationTests/ContactEvents/Create_Plain_Success_Response.jsontests/Mailtrap.IntegrationTests/ContactEvents/ContactsEventsIntegrationTests.cs
📚 Learning: 2025-09-04T08:53:06.292Z
Learnt from: vittorius
PR: railsware/mailtrap-dotnet#139
File: src/Mailtrap.Abstractions/Contacts/Models/Contact.cs:67-70
Timestamp: 2025-09-04T08:53:06.292Z
Learning: In the Mailtrap .NET client, DateTimeOffset properties should not use explicit JsonConverter attributes. All models in the codebase (TestingMessage, Inbox, EmailAttachment, etc.) handle DateTimeOffset properties using default JSON serialization without custom converters, and the Contact model should follow this same pattern for consistency.
Applied to files:
tests/Mailtrap.IntegrationTests/ContactEvents/Create_WithParams_Success_Response.jsonsrc/Mailtrap.Abstractions/ContactEvents/Models/ContactsEvent.csexamples/Mailtrap.Example.ContactEvents/Mailtrap.Example.ContactEvents.csproj
📚 Learning: 2025-09-10T17:01:49.270Z
Learnt from: dr-3lo
PR: railsware/mailtrap-dotnet#142
File: src/Mailtrap.Abstractions/ContactImports/Validators/ContactsImportRequestValidator.cs:27-30
Timestamp: 2025-09-10T17:01:49.270Z
Learning: In ContactsImportRequestValidator, ContactRequestValidator.Instance is used to validate ContactImportRequest items because ContactImportRequest inherits from ContactRequest and doesn't introduce additional validation rules that would require a separate validator.
Applied to files:
src/Mailtrap.Abstractions/ContactEvents/Validators/CreateContactsEventRequestValidator.cs
🧬 Code graph analysis (11)
src/Mailtrap.Abstractions/ContactEvents/IContactsEventsCollectionResource.cs (4)
src/Mailtrap.Abstractions/Contacts/IContactCollectionResource.cs (3)
IContactsEventCollectionResource(98-98)Task(111-111)Task(128-128)src/Mailtrap/Contacts/ContactCollectionResource.cs (3)
IContactsEventCollectionResource(34-35)Task(37-38)Task(40-41)src/Mailtrap/ContactEvents/ContactsEventCollectionResource.cs (2)
Task(11-12)Task(14-15)src/Mailtrap.Abstractions/ContactEvents/Requests/CreateContactsEventRequest.cs (1)
CreateContactsEventRequest(53-66)
src/Mailtrap.Abstractions/ContactEvents/Validators/CreateContactsEventRequestValidator.cs (1)
src/Mailtrap.Abstractions/ContactEvents/Requests/CreateContactsEventRequest.cs (1)
CreateContactsEventRequest(53-66)
tests/Mailtrap.UnitTests/Contacts/ContactCollectionResourceTests.cs (5)
tests/Mailtrap.UnitTests/TestExtensions/ResourceValidator.cs (2)
ResourceValidator(4-16)Validate(6-15)src/Mailtrap.Abstractions/Contacts/IContactCollectionResource.cs (1)
IContactsEventCollectionResource(98-98)src/Mailtrap/Contacts/ContactCollectionResource.cs (1)
IContactsEventCollectionResource(34-35)src/Mailtrap/ContactEvents/ContactsEventCollectionResource.cs (2)
ContactsEventCollectionResource(6-16)ContactsEventCollectionResource(8-9)tests/Mailtrap.UnitTests/TestConstants/UrlSegmentsTestConstants.cs (1)
UrlSegmentsTestConstants(4-22)
tests/Mailtrap.UnitTests/ContactEvents/Requests/CreateContactsEventRequestTests.cs (2)
tests/Mailtrap.IntegrationTests/ContactEvents/ContactsEventsIntegrationTests.cs (5)
TestFixture(4-216)Test(36-83)Test(85-131)Test(133-171)Test(173-215)src/Mailtrap.Abstractions/ContactEvents/Requests/CreateContactsEventRequest.cs (1)
CreateContactsEventRequest(53-66)
examples/Mailtrap.Example.ContactEvents/Program.cs (4)
src/Mailtrap.Abstractions/Contacts/Requests/CreateContactRequest.cs (1)
CreateContactRequest(19-19)src/Mailtrap.Abstractions/Contacts/IContactCollectionResource.cs (1)
IContactsEventCollectionResource(98-98)src/Mailtrap/Contacts/ContactCollectionResource.cs (1)
IContactsEventCollectionResource(34-35)src/Mailtrap.Abstractions/ContactEvents/Requests/CreateContactsEventRequest.cs (1)
CreateContactsEventRequest(53-66)
src/Mailtrap/ContactEvents/ContactsEventCollectionResource.cs (5)
tests/Mailtrap.UnitTests/ContactEvents/ContactsEventCollectionResourceTests.cs (1)
ContactsEventCollectionResource(52-52)src/Mailtrap/Contacts/ContactCollectionResource.cs (3)
IContactsEventCollectionResource(34-35)Task(37-38)Task(40-41)src/Mailtrap.Abstractions/ContactEvents/IContactsEventsCollectionResource.cs (1)
Task(23-23)src/Mailtrap.Abstractions/ContactEvents/Requests/CreateContactsEventRequest.cs (1)
CreateContactsEventRequest(53-66)src/Mailtrap/ContactFields/ContactsFieldCollectionResource.cs (1)
ContactsFieldCollectionResource(6-16)
src/Mailtrap.Abstractions/Contacts/IContactCollectionResource.cs (1)
src/Mailtrap/Contacts/ContactCollectionResource.cs (1)
IContactsEventCollectionResource(34-35)
src/Mailtrap.Abstractions/ContactEvents/Requests/CreateContactsEventRequest.cs (2)
src/Mailtrap.Abstractions/Core/Extensions/Ensure.cs (1)
Ensure(9-106)src/Mailtrap.Abstractions/ContactEvents/Validators/CreateContactsEventRequestValidator.cs (2)
CreateContactsEventRequestValidator(9-33)CreateContactsEventRequestValidator(19-32)
tests/Mailtrap.UnitTests/ContactEvents/ContactsEventCollectionResourceTests.cs (3)
tests/Mailtrap.UnitTests/Contacts/ContactCollectionResourceTests.cs (6)
Test(18-26)Test(28-36)Test(38-46)Test(52-64)Test(66-79)Test(81-92)tests/Mailtrap.UnitTests/TestConstants/UrlSegmentsTestConstants.cs (1)
UrlSegmentsTestConstants(4-22)src/Mailtrap/ContactEvents/ContactsEventCollectionResource.cs (2)
ContactsEventCollectionResource(6-16)ContactsEventCollectionResource(8-9)
tests/Mailtrap.IntegrationTests/ContactEvents/ContactsEventsIntegrationTests.cs (9)
tests/Mailtrap.UnitTests/ContactEvents/Requests/CreateContactsEventRequestTests.cs (7)
TestFixture(4-90)Test(7-17)Test(27-45)Test(47-53)Test(55-61)Test(63-75)Test(77-89)src/Mailtrap/Configuration/MailtrapClientOptions.cs (1)
JsonSerializerOptions(148-154)tests/Mailtrap.IntegrationTests/TestConstants/UrlSegmentsTestConstants.cs (1)
UrlSegmentsTestConstants(4-25)src/Mailtrap.Abstractions/ContactEvents/IContactsEventsCollectionResource.cs (1)
Task(23-23)src/Mailtrap/ContactEvents/ContactsEventCollectionResource.cs (2)
Task(11-12)Task(14-15)src/Mailtrap.Abstractions/ContactEvents/Requests/CreateContactsEventRequest.cs (1)
CreateContactsEventRequest(53-66)src/Mailtrap/Core/Constants/MimeTypes.cs (2)
MimeTypes(4-19)Application(6-11)src/Mailtrap/Core/Constants/HeaderValues.cs (1)
HeaderValues(7-12)tests/Mailtrap.IntegrationTests/TestExtensions/ValidationHelpers.cs (1)
ShouldBeEquivalentToContactResponse(25-40)
src/Mailtrap/Contacts/ContactCollectionResource.cs (2)
src/Mailtrap.Abstractions/Contacts/IContactCollectionResource.cs (1)
IContactsEventCollectionResource(98-98)src/Mailtrap/ContactEvents/ContactsEventCollectionResource.cs (2)
ContactsEventCollectionResource(6-16)ContactsEventCollectionResource(8-9)
🔇 Additional comments (21)
tests/Mailtrap.IntegrationTests/GlobalUsings.cs (1)
24-25: LGTM: ContactEvents namespaces added for integration testsMatches the new feature surface; no issues.
src/Mailtrap/GlobalUsings.cs (1)
45-47: LGTM: Runtime global usings for ContactEventsKeeps grouping aligned with other feature areas.
tests/Mailtrap.IntegrationTests/ContactEvents/Create_Plain_Success_Response.json (1)
1-5: Confirm fixture matches the real API responseEnsure these are exactly the fields the API returns for create (no missing id/timestamps or different casing). Don’t tailor fixtures to client-side converters.
tests/Mailtrap.IntegrationTests/ContactEvents/Create_WithParams_Success_Request.json (1)
1-9: Verify params typing/null handling align with server and validatorConfirm allowed scalar types and snake_case keys; ensure null values are accepted by the API and by CreateContactsEventRequestValidator.
examples/Mailtrap.Example.ContactEvents/Properties/launchSettings.json (1)
1-10: LGTM: Development profileStraightforward dev setup.
tests/Mailtrap.UnitTests/GlobalUsings.cs (1)
35-36: Do not add Mailtrap.ContactEvents.Models to tests/Mailtrap.UnitTests/GlobalUsings.cs — not neededContactsEvent is only used in integration tests/examples; tests/Mailtrap.IntegrationTests/GlobalUsings.cs already includes global using Mailtrap.ContactEvents.Models and the model exists at src/Mailtrap.Abstractions/ContactEvents/Models/ContactsEvent.cs.
Likely an incorrect or invalid review comment.
tests/Mailtrap.UnitTests/TestConstants/UrlSegmentsTestConstants.cs (1)
21-21: LGTM — Events URL segment constant; tests use it. No other "events" string literal found in tests; all usages reference UrlSegmentsTestConstants.EventsSegment (defined in tests/Mailtrap.UnitTests/TestConstants/UrlSegmentsTestConstants.cs and tests/Mailtrap.IntegrationTests/TestConstants/UrlSegmentsTestConstants.cs).examples/Mailtrap.Example.ContactEvents/Mailtrap.Example.ContactEvents.csproj (2)
1-11: Project configuration follows established patterns.The project configuration follows the established pattern for example projects in the codebase, using the centralized
mailtrap-example.propsfile for common properties and appropriately managing dependencies and content files.
3-4: Verify/pin package versions. PackageReference entries in examples/Mailtrap.Example.ContactEvents/Mailtrap.Example.ContactEvents.csproj (lines 3–4) omit explicit versions — pin them here or confirm central package management. Latest stable System.Text.Json: 9.0.8 (Aug 5, 2025). (nuget.org) Latest stable Microsoft.Extensions.Http: 9.0.9 (Sep 9, 2025). (nuget.org)src/Mailtrap.Abstractions/GlobalUsings.cs (1)
42-45: Global using statements properly organized.The ContactEvents namespace imports are correctly alphabetically positioned with the existing ContactFields imports and follow the established pattern for namespace organization in the project.
tests/Mailtrap.IntegrationTests/ContactEvents/Create_WithParams_Success_Response.json (1)
1-11: Test fixture accurately represents expected server response.The JSON fixture structure appears consistent with other test fixtures in the project and properly includes all expected fields for a contact event creation response.
src/Mailtrap/Contacts/ContactCollectionResource.cs (2)
11-11: LGTM!The EventsSegment constant follows the established naming convention and pattern used by other segment constants in the class.
34-35: Navigation method implementation is correct.The Events method properly implements the resource navigation pattern by constructing the URI with the contactId followed by the EventsSegment, matching the pattern used by other navigation methods in the class.
tests/Mailtrap.UnitTests/Contacts/ContactCollectionResourceTests.cs (1)
188-205: Unit test follows established testing patterns.The test properly validates resource creation, URI construction, and type assertions using the established ResourceValidator pattern consistent with other tests in the class.
tests/Mailtrap.IntegrationTests/TestConstants/UrlSegmentsTestConstants.cs (1)
24-24: Constant addition maintains consistency.The EventsSegment constant properly follows the established pattern and maintains alphabetical ordering with existing URL segment constants.
tests/Mailtrap.IntegrationTests/ContactEvents/Create_Plain_Success_Request.json (1)
1-3: Minimal test fixture is appropriate.The plain request fixture correctly represents a minimal contact event creation scenario with only the required "name" field.
src/Mailtrap.Abstractions/Contacts/IContactCollectionResource.cs (1)
87-98: Interface method properly documented and typed.The Events method signature and documentation follow established patterns in the interface and correctly specify the return type and parameter requirements.
src/Mailtrap.Abstractions/ContactEvents/Models/ContactsEvent.cs (1)
8-48: LGTM: response model is straightforward and consistent with existing patterns.
Paramswith JsonObjectCreationHandling.Populate avoids nulls and supports deserialization as expected.tests/Mailtrap.IntegrationTests/ContactEvents/ContactsEventsIntegrationTests.cs (2)
143-171: Nice negative‑path coverage and no‑send assertion.Asserting RequestValidationException and verifying 0 matches ensures client‑side validation blocks the HTTP call. LGTM.
Also applies to: 187-215
45-51: Fixture fidelity to server schema.Loading request/response from JSON fixtures is good. Keep fixtures mirroring real server payloads (don’t tweak to fit client), per prior guidance.
Would you confirm these fixtures were captured from actual API responses/requests?
Also applies to: 98-101
Mailtrap.sln (1)
98-99: Approve — Mailtrap.Example.ContactEvents solution wiring verified.
examples/Mailtrap.Example.ContactEvents/Mailtrap.Example.ContactEvents.csproj exists; Mailtrap.sln contains the project entry and build mappings (lines 98, 190–193, 220); examples imports mailtrap-example.props (examples/Directory.Build.props line 6).
src/Mailtrap.Abstractions/ContactEvents/IContactsEventCollectionResource.cs
Show resolved
Hide resolved
src/Mailtrap.Abstractions/ContactEvents/IContactsEventCollectionResource.cs
Show resolved
Hide resolved
tests/Mailtrap.UnitTests/ContactEvents/ContactsEventCollectionResourceTests.cs
Show resolved
Hide resolved
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.
A couple of comments, and I think it's worth paying attention to some CodeRabbit comments about interfaces and their implementation. Besides that, LGTM.
post review updates and fixes: - Added Contact Events params in example project - Made file names in consistent with class name - Removed ContactsEvent.GetAll impl - updates in integration tests to be DRY - additonal unit test
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.
Actionable comments posted: 0
🧹 Nitpick comments (2)
src/Mailtrap.Abstractions/ContactEvents/Validators/CreateContactsEventRequestValidator.cs (2)
21-21: Minor: simplify Name rule.
NotEmpty()plusLength(1, 255)is redundant. PreferMaximumLength(255)withNotEmpty()for clarity.- RuleFor(r => r.Name).NotEmpty().Length(1, 255); + RuleFor(r => r.Name) + .NotEmpty() + .MaximumLength(255);
23-29: Consider treating whitespace-only param keys as invalid.Current
NotEmpty()allows " " keys. Optionally reject whitespace and slightly simplify the guard.- When(r => r.Params != null && r.Params.Count > 0, () => + When(r => r.Params is not null, () => { - RuleForEach(r => r.Params.Keys) + RuleForEach(r => r.Params!.Keys) .Cascade(CascadeMode.Stop) - .NotEmpty() + .Must(k => !string.IsNullOrWhiteSpace(k)).WithMessage("Parameter key cannot be whitespace.") .MaximumLength(255); });
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
examples/Mailtrap.Example.ContactEvents/Program.cs(1 hunks)src/Mailtrap.Abstractions/ContactEvents/IContactsEventCollectionResource.cs(1 hunks)src/Mailtrap.Abstractions/ContactEvents/Validators/CreateContactsEventRequestValidator.cs(1 hunks)src/Mailtrap/ContactEvents/ContactsEventCollectionResource.cs(1 hunks)tests/Mailtrap.IntegrationTests/ContactEvents/ContactsEventIntegrationTests.cs(1 hunks)tests/Mailtrap.UnitTests/ContactEvents/Requests/CreateContactsEventRequestTests.cs(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- examples/Mailtrap.Example.ContactEvents/Program.cs
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-09-23T10:44:34.295Z
Learnt from: dr-3lo
PR: railsware/mailtrap-dotnet#152
File: src/Mailtrap.Abstractions/ContactEvents/IContactsEventsCollectionResource.cs:6-6
Timestamp: 2025-09-23T10:44:34.295Z
Learning: The Contact Events API backend does not provide a GetAll/list method - only Create is supported. The ContactsEventCollectionResource implementation should not include a GetAll method.
Applied to files:
src/Mailtrap.Abstractions/ContactEvents/IContactsEventCollectionResource.cssrc/Mailtrap/ContactEvents/ContactsEventCollectionResource.cs
📚 Learning: 2025-09-10T17:01:49.270Z
Learnt from: dr-3lo
PR: railsware/mailtrap-dotnet#142
File: src/Mailtrap.Abstractions/ContactImports/Validators/ContactsImportRequestValidator.cs:27-30
Timestamp: 2025-09-10T17:01:49.270Z
Learning: In ContactsImportRequestValidator, ContactRequestValidator.Instance is used to validate ContactImportRequest items because ContactImportRequest inherits from ContactRequest and doesn't introduce additional validation rules that would require a separate validator.
Applied to files:
src/Mailtrap.Abstractions/ContactEvents/Validators/CreateContactsEventRequestValidator.cs
📚 Learning: 2025-09-04T12:23:59.276Z
Learnt from: dr-3lo
PR: railsware/mailtrap-dotnet#139
File: tests/Mailtrap.IntegrationTests/Contacts/Update_Success.json:16-17
Timestamp: 2025-09-04T12:23:59.276Z
Learning: Test fixtures in the Mailtrap .NET client should accurately represent the actual server response format and should not be modified to match client-side converters or serialization preferences.
Applied to files:
tests/Mailtrap.IntegrationTests/ContactEvents/ContactsEventIntegrationTests.cs
🧬 Code graph analysis (5)
src/Mailtrap.Abstractions/ContactEvents/IContactsEventCollectionResource.cs (3)
src/Mailtrap/ContactEvents/ContactsEventCollectionResource.cs (1)
Task(11-12)tests/Mailtrap.IntegrationTests/ContactEvents/ContactsEventIntegrationTests.cs (1)
Task(36-70)src/Mailtrap.Abstractions/ContactEvents/Requests/CreateContactsEventRequest.cs (1)
CreateContactsEventRequest(53-66)
src/Mailtrap.Abstractions/ContactEvents/Validators/CreateContactsEventRequestValidator.cs (1)
src/Mailtrap.Abstractions/ContactEvents/Requests/CreateContactsEventRequest.cs (1)
CreateContactsEventRequest(53-66)
tests/Mailtrap.UnitTests/ContactEvents/Requests/CreateContactsEventRequestTests.cs (2)
tests/Mailtrap.IntegrationTests/ContactEvents/ContactsEventIntegrationTests.cs (4)
Test(72-80)Test(82-90)Test(92-130)Test(132-174)src/Mailtrap.Abstractions/ContactEvents/Requests/CreateContactsEventRequest.cs (1)
CreateContactsEventRequest(53-66)
tests/Mailtrap.IntegrationTests/ContactEvents/ContactsEventIntegrationTests.cs (8)
tests/Mailtrap.UnitTests/ContactEvents/Requests/CreateContactsEventRequestTests.cs (8)
TestFixture(4-106)Test(7-17)Test(27-46)Test(48-61)Test(63-69)Test(71-77)Test(79-91)Test(93-105)src/Mailtrap/Configuration/MailtrapClientOptions.cs (1)
JsonSerializerOptions(148-154)src/Mailtrap.Abstractions/ContactEvents/IContactsEventCollectionResource.cs (1)
Task(23-23)src/Mailtrap/ContactEvents/ContactsEventCollectionResource.cs (1)
Task(11-12)src/Mailtrap.Abstractions/ContactEvents/Requests/CreateContactsEventRequest.cs (1)
CreateContactsEventRequest(53-66)src/Mailtrap/Core/Constants/MimeTypes.cs (2)
MimeTypes(4-19)Application(6-11)src/Mailtrap/Core/Constants/HeaderValues.cs (1)
HeaderValues(7-12)tests/Mailtrap.IntegrationTests/TestExtensions/ValidationHelpers.cs (1)
ShouldBeEquivalentToContactResponse(25-40)
src/Mailtrap/ContactEvents/ContactsEventCollectionResource.cs (5)
tests/Mailtrap.UnitTests/ContactEvents/ContactsEventCollectionResourceTests.cs (1)
ContactsEventCollectionResource(52-52)src/Mailtrap/Contacts/ContactCollectionResource.cs (3)
IContactsEventCollectionResource(34-35)Task(37-38)Task(40-41)src/Mailtrap.Abstractions/ContactEvents/IContactsEventCollectionResource.cs (1)
Task(23-23)tests/Mailtrap.IntegrationTests/ContactEvents/ContactsEventIntegrationTests.cs (1)
Task(36-70)src/Mailtrap.Abstractions/ContactEvents/Requests/CreateContactsEventRequest.cs (1)
CreateContactsEventRequest(53-66)
🔇 Additional comments (9)
src/Mailtrap.Abstractions/ContactEvents/IContactsEventCollectionResource.cs (1)
6-24: LGTM: interface shape matches backend (Create only).Contract is minimal and consistent with API capabilities.
tests/Mailtrap.IntegrationTests/ContactEvents/ContactsEventIntegrationTests.cs (3)
36-70: Nice end-to-end success path.Good fixture usage and strict header assertions;
VerifyNoOutstandingExpectation()confirms exact call.
92-130: Good validation guard: no HTTP on invalid name.The test ensures local validation short-circuits and no network call is made.
132-174: Good validation guard: no HTTP on invalid param key.Covers oversized key and asserts zero matches on mock.
src/Mailtrap/ContactEvents/ContactsEventCollectionResource.cs (1)
11-12: LGTM: thin delegate to base with ConfigureAwait(false).Matches interface and project patterns.
tests/Mailtrap.UnitTests/ContactEvents/Requests/CreateContactsEventRequestTests.cs (4)
7-17: Record-with test reads well.Verifies copy semantics and Params immutability expectations.
19-25: Constructor null/empty guard covered.Asserts ParamName; good specificity.
63-77: Boundary tests are solid.Covers 1 and 255 lengths for name and param tag.
79-105: Invalid-length cases covered.Ensures validator fails at 256 for both name and key.
Motivation
Contacts Events API support into .NET client #151
Changes
How to test
Summary by CodeRabbit