Skip to content

Conversation

@dr-3lo
Copy link
Collaborator

@dr-3lo dr-3lo commented Sep 15, 2025

Motivation

Contacts Import API support into .NET client to resolve #124

Changes

  • Added Contact Lists management interfaces, models, requests, and validation
  • Added example project to demonstrate Contact Lists API usage
  • Updated Contacts interface to provide access to Contact Lists
  • Added Contact Lists unit tests
  • Added Contact Lists integration tests
  • Extended Contacts unit tests to cover new methods for accessing lists and imports

Also

How to test

Summary by CodeRabbit

  • New Features

    • Full Contacts Lists support (list, create, details, update, delete) and navigation from Contacts to Imports and Lists.
    • Listing and creation operations for Contacts.
    • Runnable example demonstrating Contact Lists usage with configuration.
  • Bug Fixes

    • Improved JSON deserialization reliability by annotating parameterless constructors for serializers.
    • Aligned update/import models to better support include/exclude list semantics.
  • Documentation

    • Enhanced XML docs and added example appsettings.
  • Tests

    • Added comprehensive integration and unit tests, fixtures, and test helpers.

dr-3lo and others added 8 commits September 10, 2025 13:49
- Added contact imports management interfaces, models, requests, and validation

- Added example project to deminstrate Contact Imports API usage

- Updated Contacts Interface to provide access to Contact Imports
- Added Contacts Import Unit tests
- Added Contacts Import Integrational tests
- Updates in Contacts Import and Contacts models for unification and to support serialization
- Corrected documentation for contact imports and requests
Enhance validation for ContactsImportRequest and improve documentation
- Enhance validation tests for ContactsImportRequest to include edge cases for collection size and entries format

- Corrected ContactImportRequest documentation
- Corrected contact import variable names and
- updated contact import status property
- corrections in contact import integrational tests
– Added Contact Lists management interfaces, models, requests, and validation
– Added example project to demonstrate Contact Lists API usage
– Updated Contacts interface to provide access to Contact Lists
– Added Contact Lists unit tests
– Added Contact Lists integration tests
– Extended Contacts unit tests to cover new methods for accessing lists and imports

Implemented comparer for Contacts in Contacts integration tests for feature #140: now it properly compares the actual results of requests with the expected ones.
- XML Docs corrections
- added tests for DateTimeToUnixMsNullableJsonConverter
@coderabbitai
Copy link

coderabbitai bot commented Sep 15, 2025

Walkthrough

Adds Contact Lists and import navigation: new abstractions, models, validators, runtime resources, example project, serializer annotations, global usings, and companion unit/integration tests and test helpers. Also adds two example projects to the solution and updates solution nesting and configuration mappings.

Changes

Cohort / File(s) Summary
Solution setup
Mailtrap.sln
Adds Mailtrap.Example.ContactImports and Mailtrap.Example.ContactLists projects, solution configuration mappings, and nests them under the examples solution folder.
Examples: ContactLists
examples/Mailtrap.Example.ContactLists/*
New example app, csproj with package refs, Program.cs, appsettings.json, and launchSettings.json.
Examples: ContactImports csproj update
examples/Mailtrap.Example.ContactImports/Mailtrap.Example.ContactImports.csproj
Removed explicit PackageReference version overrides.
Abstractions: Contact Lists
src/Mailtrap.Abstractions/ContactLists/*
Adds IContactsListCollectionResource, IContactsListResource, ContactsList model, ContactsListRequest, and ContactsListRequestValidator.
Abstractions: Contacts & Imports changes
src/Mailtrap.Abstractions/Contacts/*, src/Mailtrap.Abstractions/ContactImports/*
Adds navigation methods (Imports/Import/Lists/List), new contact-related request types updated with [JsonConstructor], doc-comment tweaks, and global using additions.
Global usings (runtime & abstractions)
src/Mailtrap.GlobalUsings.cs, src/Mailtrap.Abstractions/GlobalUsings.cs
Adds global usings for ContactImports and ContactLists namespaces.
Runtime: Contact Lists resources
src/Mailtrap/ContactLists/*
Implements ContactsListCollectionResource (GetAll/Create) and ContactsListResource (GetDetails/Update/Delete).
Runtime: Contacts navigation
src/Mailtrap/Contacts/ContactCollectionResource.cs
Adds Imports(), Import(id), Lists(), List(id) and path-segment constants.
Integration tests: Contact Lists & Imports
tests/Mailtrap.IntegrationTests/ContactLists/*, tests/Mailtrap.IntegrationTests/ContactImports/*
New integration tests for lists and imports (CRUD + validation) and JSON fixtures for list scenarios.
Tests: Helpers, globals, constants
tests/*/TestExtensions/*, tests/*/GlobalUsings.cs, tests/*/TestConstants/UrlSegmentsTestConstants.cs
Adds email/file/validation helpers, ValidationHelpers, NextEmail helper, fixes param name, adds Imports/Lists URL constants, and new global usings.
Unit tests: Contact Lists & Contacts navigation
tests/Mailtrap.UnitTests/ContactLists/*, tests/Mailtrap.UnitTests/Contacts/*
New unit tests for ContactsList resources, Contacts nested resource navigation, and converter tests; adds test URL constants and test global usings.
Tests: Contacts expected-response comparison
tests/Mailtrap.IntegrationTests/Contacts/ContactsIntegrationTests.cs, tests/.../ValidationHelpers.cs
Tests now deserialize expected responses from fixtures and compare actual results to expected via helper comparers.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Dev
  participant ExampleApp as Example App
  participant MailtrapClient as MailtrapClient
  participant ContactsCol as Contacts Collection
  participant ListsCol as Contact Lists Collection
  participant ListRes as Contact List Resource
  participant API as Mailtrap HTTP API

  Dev->>ExampleApp: run
  ExampleApp->>MailtrapClient: configure (ApiToken)
  ExampleApp->>MailtrapClient: Account(id).Contacts()
  MailtrapClient->>ContactsCol: access collection

  Note over ContactsCol,ListsCol: New navigation methods
  ContactsCol->>ListsCol: Lists()
  ListsCol->>API: GET /accounts/{id}/contacts/lists
  API-->>ListsCol: 200 [ContactsList[]]
  ListsCol-->>ExampleApp: IList<ContactsList>

  alt create list
    ExampleApp->>ListsCol: Create(request)
    ListsCol->>API: POST /accounts/{id}/contacts/lists
    API-->>ListsCol: 201 ContactsList
    ListsCol-->>ExampleApp: ContactsList
  end

  ExampleApp->>ContactsCol: List(listId)
  ContactsCol->>ListRes: resource for /lists/{listId}

  par details / update / delete
    ListRes->>API: GET /accounts/{id}/contacts/lists/{listId}
    API-->>ListRes: 200 ContactsList
    ListRes->>API: PATCH /accounts/{id}/contacts/lists/{listId}
    API-->>ListRes: 200 ContactsList
    ListRes->>API: DELETE /accounts/{id}/contacts/lists/{listId}
    API-->>ListRes: 204 No Content
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

Possibly related PRs

Suggested reviewers

  • zhaparoff
  • vittorius
  • mklocek

Poem

In carrot-code burrows I hopped with delight,
I stitched lists and imports through day and night.
Validators snug, example app set to run,
Tests munch on fixtures — oh what fun! 🥕🐇

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Title Check ✅ Passed The PR title "Feature/124 contact lists" is concise and directly references the main change (adding contact lists) and the tracked issue number, giving reviewers a clear, scannable summary of the branch's intent. It avoids noise and is appropriately short for a feature branch title.
Linked Issues Check ✅ Passed The changes implement the Contact Lists functionality required by issue #124 (new abstractions, models, requests, validators, RestResource implementations, updated ContactCollectionResource navigation, unit and integration tests, and an example project) and address issue #140 by adding test utilities and updating integration tests to deserialize expected responses and assert equivalence (ValidationHelpers.ShouldBeEquivalentToContactResponse and updated test flows). The code-level artifacts and tests map directly to the stated objectives and provide both API surface and coverage for the linked issues.
Out of Scope Changes Check ✅ Passed I did not find substantive out‑of‑scope changes: most modifications relate to contact lists/imports, test comparer helpers, tests, and the example project which align with the PR objectives. There are a few minor housekeeping edits (example csproj version removal and added converter unit tests) that are peripheral to the feature but are low‑risk and self‑contained.
Description Check ✅ Passed The PR description follows the repository template by including Motivation, a detailed Changes list, and a How to test section with checkboxes and links to the new example and tests; it also documents secondary work (comparer and converter tests). The Images/GIFs section from the template is unused but that is non‑critical. Overall the description provides sufficient context for reviewers and testers to understand scope and validation steps.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/124-Contact-Lists

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.

  • Built-in checks – Quickly apply ready-made checks to enforce title conventions, require pull request descriptions that follow templates, validate linked issues for compliance, and more.
  • Custom agentic checks – Define your own rules using CodeRabbit’s advanced agentic capabilities to enforce organization-specific policies and workflows. For example, you can instruct CodeRabbit’s agent to verify that API documentation is updated whenever API schema files are modified in a PR. Note: Upto 5 custom checks are currently allowed during the preview period. Pricing for this feature will be announced in a few weeks.

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (48)
tests/Mailtrap.UnitTests/Contacts/Converters/DateTimeToUnixMsNullableJsonConverterTests.cs (3)

29-37: Strengthen assertion: verify JSON number kind, not just string equality

Assert the JSON token type is Number and its value equals expected ms. This makes the test resilient to incidental whitespace/formatting.

Apply:

-        // Assert
-        json.Should().Be(expectedMs.ToString(CultureInfo.InvariantCulture));
+        // Assert
+        using var doc = System.Text.Json.JsonDocument.Parse(json);
+        var root = doc.RootElement;
+        root.ValueKind.Should().Be(System.Text.Json.JsonValueKind.Number);
+        root.GetInt64().Should().Be(expectedMs);

63-70: Reduce brittleness of exception message assertion

Messages can drift; assert on content instead of full pattern.

-        act.Should().Throw<JsonException>().WithMessage("*Expected number for Unix time milliseconds*");
+        act.Should().Throw<JsonException>()
+           .Which.Message.Should().Contain("Expected number");

1-71: Add a few edge‑case tests (offsets, negatives, non‑integral numbers)

Covers important edges without overfitting.

@@
     public void Read_InvalidTokenType_ThrowsException()
     {
         // Arrange
         var json = "\"not a number\"";
         // Act & Assert
         var act = () => JsonSerializer.Deserialize<DateTimeOffset?>(json, _options);
-        act.Should().Throw<JsonException>().WithMessage("*Expected number for Unix time milliseconds*");
+        act.Should().Throw<JsonException>().Which.Message.Should().Contain("Expected number");
     }
 }
+
+    [Test]
+    public void Write_LocalOffset_SerializesToUnixMs()
+    {
+        // Arrange
+        var local = new DateTimeOffset(2020, 01, 01, 00, 00, 00, TimeSpan.FromHours(-5));
+        var expectedMs = local.ToUnixTimeMilliseconds();
+        // Act
+        var json = JsonSerializer.Serialize<DateTimeOffset?>(local, _options);
+        // Assert
+        using var doc = System.Text.Json.JsonDocument.Parse(json);
+        doc.RootElement.GetInt64().Should().Be(expectedMs);
+    }
+
+    [Test]
+    public void Read_NegativeUnixMs_DeserializesToCorrectDate()
+    {
+        // Arrange
+        long ms = -1000; // 1969-12-31T23:59:59Z
+        var json = ms.ToString(CultureInfo.InvariantCulture);
+        // Act
+        var result = JsonSerializer.Deserialize<DateTimeOffset?>(json, _options);
+        // Assert
+        result.Should().Be(DateTimeOffset.FromUnixTimeMilliseconds(ms));
+    }
+
+    [Test]
+    public void Read_NonIntegralNumber_ThrowsJsonException()
+    {
+        // Arrange: exponent/decimal form should not be accepted by GetInt64
+        var json = "1.5778368e12";
+        // Act
+        var act = () => JsonSerializer.Deserialize<DateTimeOffset?>(json, _options);
+        // Assert
+        act.Should().Throw<JsonException>();
+    }
src/Mailtrap.Abstractions/GlobalUsings.cs (1)

30-36: Add missing root namespace for ContactLists (consistency with ContactImports)

You added Mailtrap.ContactImports root but not Mailtrap.ContactLists. Recommend adding it for parity and fewer fully‑qualified references.

 global using Mailtrap.ContactImports.Requests;
 global using Mailtrap.ContactImports.Validators;
+global using Mailtrap.ContactLists;
 global using Mailtrap.ContactLists.Models;
 global using Mailtrap.ContactLists.Requests;
 global using Mailtrap.ContactLists.Validators;
examples/Mailtrap.Example.ContactLists/appsettings.json (1)

1-17: Keep secrets out of source; prefer User Secrets or env vars

Good sample config. Please document using dotnet user-secrets or environment variables for Mailtrap:ApiToken to avoid accidental key commits.

src/Mailtrap.Abstractions/Contacts/Requests/CreateContactRequest.cs (1)

21-24: Parameterless ctor: clarify serializer intent and selection

To make constructor selection explicit and avoid ambiguity with the (string email) ctor, consider marking the parameterless ctor with [JsonConstructor]. Also please confirm the base ContactRequest supports parameterless construction in this PR.

     /// <summary>
     /// Parameterless instance constructor for serializers.
     /// </summary>
-    public CreateContactRequest() { }
+    [JsonConstructor]
+    public CreateContactRequest() { }
tests/Mailtrap.IntegrationTests/TestExtensions/EmailAddressHelpers.cs (1)

14-49: Consider edge case handling and domain validation.

The email generation logic is mostly sound, but there are a few areas for improvement:

  1. Line 39-42: When outputLength is less than minimum requirements, returning random.GetString(outputLength.Value) produces a random string that's not a valid email format, which may cause test failures.

  2. Lines 24-33: No validation is performed on the provided domain parameter - it could contain invalid characters or format.

  3. Line 46: The calculation usernameLength ?? defaultUsernameLength could result in a negative value if outputLength is very small but still >= minEmailLength.

Consider these improvements:

// Explicit check for valid outputLength
if (outputLength.HasValue && outputLength < minEmailLength)
{
-    return random.GetString(outputLength.Value);
+    throw new ArgumentException($"Output length {outputLength.Value} is too small for a valid email. Minimum required: {minEmailLength}", nameof(outputLength));
}

// Generation of username with optimal length
var usernameLength = outputLength - atSymbol.Length - domainPart.Length;
+if (usernameLength < 1)
+{
+    throw new ArgumentException($"Cannot generate valid email with specified output length {outputLength}", nameof(outputLength));
+}
var username = random.GetString(usernameLength ?? defaultUsernameLength);
tests/Mailtrap.IntegrationTests/TestExtensions/ValidationHelpers.cs (2)

6-17: Good reuse-safety on StringContent stream; minor robustness tweak available

Resetting the stream after deserialization is correct to allow reuse. Optionally also seek to 0 before deserialization to be defensive if a reused content was previously read.

     var responseStream = await responseContent.ReadAsStreamAsync();
+    if (responseStream.CanSeek)
+    {
+        responseStream.Position = 0;
+    }
     var expectedResponse = await JsonSerializer.DeserializeAsync<TValue>(responseStream, jsonSerializerOptions);
     if (responseStream.CanSeek)
     {
         responseStream.Position = 0; // Reset stream position
     }

19-40: Tidy up: fix typos, avoid shadowing, and use GetRawText for stable JsonElement comparison

  • Fix typos in XML docs/comments.
  • Avoid shadowing the method parameter name with a local variable named expected.
  • Prefer JsonElement.GetRawText() over ToString() for exact structural equality.
-    /// <typeparam name="TValue">Suppose to be <see cref="ContactResponse"/> and derived classes.</typeparam>
-    /// <param name="result">Object with actial result</param>
+    /// <typeparam name="TValue">Supposed to be <see cref="ContactResponse"/> and derived classes.</typeparam>
+    /// <param name="result">Object with actual result</param>
     /// <param name="expected">Object with expected results</param>
     internal static void ShouldBeEquivalentToContactResponse<TValue>(this TValue result, TValue expected)
         where TValue : class
     {
         result.Should()
             .NotBeNull()
             .And
             .BeEquivalentTo(expected, options => options
             // Convert JsonElement to string before comparison
-            // this should allow to correctly compare Dictionaty<string, object> like Contact.Fields
+            // this should allow to correctly compare Dictionary<string, object> like Contact.Fields
             .Using<JsonElement>(ctx =>
             {
-                var expected = ctx.Expectation.ToString();
-                var actual = ctx.Subject.ToString();
-                actual.Should().Be(expected);
+                var expectedText = ctx.Expectation.GetRawText();
+                var actualText = ctx.Subject.GetRawText();
+                actualText.Should().Be(expectedText);
             }).WhenTypeIs<JsonElement>());
     }
tests/Mailtrap.IntegrationTests/Contacts/ContactsIntegrationTests.cs (3)

85-86: Silence nullable warnings at call site

You already assert not null; use the null‑forgiving operator when passing expectedResponse to the comparer.

-expectedResponse.Should().NotBeNull();
+expectedResponse.Should().NotBeNull();
 ...
-result.ShouldBeEquivalentToContactResponse(expectedResponse);
+result.ShouldBeEquivalentToContactResponse(expectedResponse!);

Also applies to: 114-114


165-167: Repeat: apply null‑forgiving for clarity

Same as above for GetDetails_Success.

-expectedResponse.Should().NotBeNull();
+expectedResponse.Should().NotBeNull();
 ...
-result.ShouldBeEquivalentToContactResponse(expectedResponse);
+result.ShouldBeEquivalentToContactResponse(expectedResponse!);

Also applies to: 194-194


205-205: Repeat: apply null‑forgiving for Update_Success

Keep consistency across tests.

-expectedResponse.Should().NotBeNull();
+expectedResponse.Should().NotBeNull();
 ...
-result.ShouldBeEquivalentToContactResponse(expectedResponse);
+result.ShouldBeEquivalentToContactResponse(expectedResponse!);

Also applies to: 209-211, 239-239

examples/Mailtrap.Example.ContactImports/Mailtrap.Example.ContactImports.csproj (1)

3-4: Confirm VersionOverride usage; prefer central versions or explicit Version.

If the repo uses Central Package Management (Directory.Packages.props), VersionOverride is fine; otherwise use Version for clarity.

Apply if not using CPM:

-    <PackageReference Include="Microsoft.Extensions.Http" VersionOverride="9.0.8" />
-    <PackageReference Include="System.Text.Json" VersionOverride="9.0.7" />
+    <PackageReference Include="Microsoft.Extensions.Http" Version="9.0.8" />
+    <PackageReference Include="System.Text.Json" Version="9.0.7" />
tests/Mailtrap.UnitTests/ContactImports/ContactsImportCollectionResourceTests.cs (1)

1-52: Add coverage for Create() behavior.

Consider tests verifying Create() delegates to the correct command with the given request and passes the CancellationToken.

tests/Mailtrap.UnitTests/ContactLists/ContactsListResourceTests.cs (1)

1-52: Add behavior tests for GetDetails/Update/Delete.

Mock and assert correct command invocation and token flow for each method.

src/Mailtrap/ContactLists/ContactsListResource.cs (1)

6-15: Solid implementation; consider explicit null-guard on Update request.

If base Update(...) doesn’t already throw on null request, add a fast ArgumentNullException here to fail early.

Possible tweak:

     public async Task<ContactsList> Update(ContactsListRequest request, CancellationToken cancellationToken = default)
-        => await Update<ContactsListRequest, ContactsList>(request, cancellationToken).ConfigureAwait(false);
+    {
+        if (request is null) throw new ArgumentNullException(nameof(request));
+        return await Update<ContactsListRequest, ContactsList>(request, cancellationToken).ConfigureAwait(false);
+    }
src/Mailtrap.Abstractions/Contacts/Requests/ContactRequest.cs (1)

27-28: Note: object-typed Fields may deserialize numbers as JsonElement.
If consumers rely on numeric/string fidelity (e.g., zip codes), consider documenting this or offering a typed alternative/converter.

examples/Mailtrap.Example.ContactImports/appsettings.json (1)

14-16: Avoid embedding secrets in sample config; prefer env override.
Keep placeholder, but recommend reading MAILTRAP_API_TOKEN from environment with config fallback to avoid accidental commits of real tokens.

tests/Mailtrap.UnitTests/ContactLists/Requests/ContactsListRequestTests.cs (2)

8-13: Fix test names: “Email” → “Name”; clarify initialization name.
Method names reference Email but the subject is ContactsListRequest.Name.

Apply:

-    public void Constructor_ShouldThrowArgumentNullException_WhenEmailIsNull()
+    public void Constructor_ShouldThrowArgumentNullException_WhenNameIsNull()
@@
-    public void Constructor_ShouldThrowArgumentNullException_WhenEmailIsEmpty()
+    public void Constructor_ShouldThrowArgumentNullException_WhenNameIsEmpty()
@@
-    public void Constructor_ShouldInitializeFieldsCorrectly()
+    public void Constructor_ShouldInitializeNameCorrectly()

Also applies to: 16-21, 24-34


36-48: Add a positive boundary test (length=255).
Complements the failing-case test at 256 to lock the validator’s upper bound.

tests/Mailtrap.IntegrationTests/ContactImports/Create_Success_Request.json (1)

6-9: Zip/postal codes should be strings to preserve leading zeros.
Using numbers risks truncation of leading zeros in real data.

Apply:

-        "zip_code": 11111
+        "zip_code": "11111"
@@
-        "zip_code": 22222
+        "zip_code": "22222"

Also applies to: 24-27

src/Mailtrap.Abstractions/ContactLists/Validators/ContactsListRequestValidator.cs (1)

20-21: Reject whitespace-only names; keep length rule.
Current NotEmpty allows " ". Add a whitespace check.

Apply:

-        RuleFor(r => r.Name).NotEmpty().Length(1, 255);
+        RuleFor(r => r.Name)
+            .Must(n => !string.IsNullOrWhiteSpace(n))
+            .WithMessage("Name must not be empty or whitespace.")
+            .Length(1, 255);
tests/Mailtrap.UnitTests/ContactImports/ContactsImportResourceTests.cs (1)

39-47: Consider a unit test for GetDetails path/command dispatch.
Add a test that verifies the resource issues a GET for the built URI (mock the command factory) and honors CancellationToken.

tests/Mailtrap.IntegrationTests/TestConstants/UrlSegmentsTestConstants.cs (1)

21-22: Unify URL segment constants across test projects.
tests/Mailtrap.IntegrationTests/TestConstants/UrlSegmentsTestConstants.cs defines EmailsSegment = "messages" while tests/Mailtrap.UnitTests/TestConstants/UrlSegmentsTestConstants.cs defines MessagesSegment = "messages"; align the identifier names or extract a shared test-constants module to avoid drift.

src/Mailtrap/ContactImports/ContactsImportResource.cs (1)

3-5: Nit: tighten summary wording.

Consider clarifying this is the single-import resource (details for a specific import), not the collection.

 /// <summary>
-/// Implementation of Contact Imports API operations.
+/// Resource for a specific Contacts Import (fetches details/status).
 /// </summary>
src/Mailtrap.Abstractions/ContactImports/IContactsImportCollectionResource.cs (2)

14-16: Fix misleading XML doc sentence.

“List all contacts with details into request” reads wrong for a create/import call.

-    /// List all contacts with details into <paramref name="request"/>.
+    /// Provide the contacts to import in the <paramref name="request"/>.

25-27: Clarify return description.

Be explicit that the result is the created import descriptor with ID and initial status.

-    /// Contact import id and status.
+    /// ContactsImport containing the import ID and initial status.
tests/Mailtrap.UnitTests/ContactImports/Requests/ContactsImportRequestTests.cs (2)

37-53: Mark the 50,001‑items test as slow to keep default CI runs snappy.

This test builds a 50k+ list; flag it to allow selective execution.

-    [Test]
+    [Test, Category("Slow")]
     public void Validate_ShouldFail_WhenProvidedCollectionSizeIsInvalid([Values(0, 50001)] int size)

95-102: Stabilize “valid email” generation.

Avoid rare collisions with special chars from Random.GetString; use a deterministic, always‑valid email.

-    private static ContactImportRequest RandomContactImportRequest()
-    {
-        var email = TestContext.CurrentContext.Random.GetString(5)
-                    + "@"
-                    + TestContext.CurrentContext.Random.GetString(5)
-                    + ".com";
-        return new ContactImportRequest(email);
-    }
+    private static ContactImportRequest RandomContactImportRequest()
+    {
+        var email = $"{Guid.NewGuid():N}@example.test";
+        return new ContactImportRequest(email);
+    }
examples/Mailtrap.Example.ContactLists/Program.cs (2)

26-27: Don’t hardcode account ID; read from config and validate.

Improves portability of the sample.

-    var accountId = 12345;
-    IAccountResource accountResource = mailtrapClient.Account(accountId);
+    var accountId = config.GetValue<long>("AccountId");
+    if (accountId <= 0)
+    {
+        logger.LogError("Configure 'Mailtrap:AccountId' in appsettings.json or environment.");
+        Environment.ExitCode = 1;
+        return;
+    }
+    IAccountResource accountResource = mailtrapClient.Account(accountId);

21-23: Thread a CancellationToken from host lifetime through SDK calls.

Helps graceful shutdown and mirrors SDK APIs.

-ILogger<Program> logger = host.Services.GetRequiredService<ILogger<Program>>();
-IMailtrapClient mailtrapClient = host.Services.GetRequiredService<IMailtrapClient>();
+ILogger<Program> logger = host.Services.GetRequiredService<ILogger<Program>>();
+IMailtrapClient mailtrapClient = host.Services.GetRequiredService<IMailtrapClient>();
+var lifetime = host.Services.GetRequiredService<IHostApplicationLifetime>();
+var ct = lifetime.ApplicationStopping;
@@
-    IList<ContactsList> contactsLists = await contactsListsResource.GetAll();
+    IList<ContactsList> contactsLists = await contactsListsResource.GetAll(ct);
@@
-        contactsList = await contactsListsResource.Create(createContactsListRequest);
+        contactsList = await contactsListsResource.Create(createContactsListRequest, ct);
@@
-    ContactsList contactsListResponse = await contactsListResource.GetDetails();
+    ContactsList contactsListResponse = await contactsListResource.GetDetails(ct);
@@
-    ContactsList updateContactsListResponse = await contactsListResource.Update(updateContactsListRequest);
+    ContactsList updateContactsListResponse = await contactsListResource.Update(updateContactsListRequest, ct);
@@
-    await contactsListResource.Delete();
+    await contactsListResource.Delete(ct);

Also applies to: 36-37, 46-47, 54-58, 61-63, 67-68

src/Mailtrap.Abstractions/Contacts/Requests/ContactImportRequest.cs (1)

15-18: Doc: capture constraints in XML.

Document that IDs must be positive and disjoint; helps consumers and aligns with added validation.

-    /// Contact list IDs to include.
+    /// Contact list IDs to include (positive, unique, and not present in list_ids_excluded).
@@
-    /// Contact list IDs to exclude.
+    /// Contact list IDs to exclude (positive, unique, and not present in list_ids_included).

Also applies to: 26-29

examples/Mailtrap.Example.ContactImports/Program.cs (4)

64-69: Avoid FailFast; the subsequent throw is unreachable

Environment.FailFast terminates the process immediately and prevents graceful disposal/flush. The following throw is dead code. Prefer letting the exception propagate or setting an exit code.

 catch (Exception ex)
 {
     logger.LogError(ex, "An error occurred during API call.");
-    Environment.FailFast(ex.Message);
-    throw;
+    throw;
 }

28-30: Don’t hardcode accountId; pull from configuration

Keeps the sample copy‑pasteable across environments.

-    var accountId = 12345;
+    long accountId = config.GetValue<long>("AccountId");

49-50: Log stable identifiers (Id/Status) instead of the whole object

Improves log usefulness and avoids ToString()-dependent output.

-    logger.LogInformation("Created contact import: {Import}", importResponse);
+    logger.LogInformation("Created contact import: Id={ImportId}, Status={Status}", importResponse.Id, importResponse.Status);

-    logger.LogInformation("Contacts Import Details: {Details}", contactsImportDetails);
+    logger.LogInformation("Contacts Import Details: Id={ImportId}, Status={Status}", contactsImportDetails.Id, contactsImportDetails.Status);

Also applies to: 56-57


49-49: Optionally pass a CancellationToken from ApplicationStopping

Allows Ctrl+C and host shutdown to cancel in‑flight requests.

+    var ct = host.Services.GetRequiredService<IHostApplicationLifetime>().ApplicationStopping;
-    ContactsImport importResponse = await contactsImportsResource.Create(importRequest);
+    ContactsImport importResponse = await contactsImportsResource.Create(importRequest, ct);
 ...
-    ContactsImport contactsImportDetails = await contactsImportResource.GetDetails();
+    ContactsImport contactsImportDetails = await contactsImportResource.GetDetails(ct);

Also applies to: 56-56

src/Mailtrap.Abstractions/ContactLists/Requests/ContactsListRequest.cs (1)

28-29: Doc nit: tighten wording

Minor grammar/clarity.

-    /// Contacts List's <paramref name="name"/> must be min 1 characters and max 255 characters long.
+    /// The <paramref name="name"/> must be between 1 and 255 characters.
src/Mailtrap.Abstractions/ContactLists/IContactsListCollectionResource.cs (1)

19-20: Prefer IReadOnlyList in public API

Avoids exposing mutability in return types while remaining source/ABI compatible with List.

-    public Task<IList<ContactsList>> GetAll(CancellationToken cancellationToken = default);
+    public Task<IReadOnlyList<ContactsList>> GetAll(CancellationToken cancellationToken = default);
src/Mailtrap.Abstractions/ContactLists/IContactsListResource.cs (1)

50-55: Doc typo: “contact” → “contacts list”.

Fix copy-paste in the Delete remarks.

-    /// After deletion of the contact, represented by the current resource instance, it will be no longer available.<br />
+    /// After deletion of the contacts list, represented by the current resource instance, it will be no longer available.<br />
tests/Mailtrap.IntegrationTests/ContactLists/ContactsListIntegrationTests.cs (1)

84-90: Silence nullable warning when using expectedResponse.

Dereferencing expectedResponse.Name may warn; assert+bang or extract a non-null local.

-        var expectedResponse = await responseContent.DeserializeStringContentAsync<ContactsList>(_jsonSerializerOptions);
-        expectedResponse.Should().NotBeNull();
-
-        var request = new ContactsListRequest(expectedResponse.Name);
+        var expectedResponse = await responseContent.DeserializeStringContentAsync<ContactsList>(_jsonSerializerOptions);
+        expectedResponse.Should().NotBeNull();
+        var expected = expectedResponse!;
+
+        var request = new ContactsListRequest(expected.Name);
src/Mailtrap/Contacts/ContactCollectionResource.cs (1)

10-26: Consider centralizing path segments.

If a shared UrlSegments exists, add Imports/List constants there to avoid string duplication across resources and tests.

src/Mailtrap.Abstractions/ContactImports/Requests/ContactsImportRequest.cs (1)

3-7: Nit: summary wording.

This type is used to start imports; “CRUD operations” is misleading. Consider “Bulk contacts import request object.”

-/// Generic request object for contacts import CRUD operations.
+/// Request object for starting a bulk contacts import.
src/Mailtrap.Abstractions/ContactImports/Validators/ContactsImportRequestValidator.cs (5)

4-7: Fix inaccurate XML summary.

This validator targets ContactsImportRequest and list bounds, not “contact’s email”. Update to reflect scope.

-/// Validator for Create/Update contact requests.<br />
-/// Ensures contact's email is not empty and length is within the allowed range.
+/// Validator for ContactsImportRequest.
+/// Ensures the Contacts collection size is within allowed bounds and each item is valid.

10-11: Visibility of constants within an internal type.

‘public’ members on an internal class can’t escape the assembly; prefer internal/private for clarity.

-    public const int MaxContactsPerRequest = 50_000;
-    public const int MinContactsPerRequest = 1;
+    internal const int MaxContactsPerRequest = 50_000;
+    internal const int MinContactsPerRequest = 1;

22-26: Simplify rules and add actionable messages.

NotEmpty() + Count >= 1 is redundant. Also, add messages for better UX.

-        RuleFor(r => r.Contacts)
-            .Cascade(CascadeMode.Stop)
-            .NotEmpty()
-            .Must(list => list != null && list.Count is >= MinContactsPerRequest and <= MaxContactsPerRequest);
+        RuleFor(r => r.Contacts)
+            .Cascade(CascadeMode.Stop)
+            .NotNull().WithMessage("'Contacts' must not be null.")
+            .Must(list => list!.Count is >= MinContactsPerRequest and <= MaxContactsPerRequest)
+            .WithMessage($"'Contacts' must contain between {MinContactsPerRequest} and {MaxContactsPerRequest} items.");

27-30: Per‑item validator usage — LGTM.

Delegating to ContactRequestValidator.Instance aligns with the inheritance model noted in prior PRs. Optionally guard enumeration.

-        RuleForEach(r => r.Contacts)
+        RuleForEach(r => r.Contacts)
             .NotNull()
             .SetValidator(ContactRequestValidator.Instance);
+            // .When(r => r.Contacts is { Count: > 0 }) // optional: skip when null/empty

10-11: Confirmed: MaxContactsPerRequest = 50,000 — matches Mailtrap docs; add docs link

Verified via Mailtrap changelog and features/pricing (50,000 contacts per import request).

File: src/Mailtrap.Abstractions/ContactImports/Validators/ContactsImportRequestValidator.cs
Lines: 10-11

    public const int MaxContactsPerRequest = 50_000;
    public const int MinContactsPerRequest = 1;

Action: Add an inline comment above MaxContactsPerRequest with a link to the Mailtrap docs/changelog.

Mailtrap.sln (1)

174-181: Configs added for Debug/Release — OK.
Example projects exist and ActiveCfg + Build.0 mappings are present for both; if CI shouldn't build examples, remove the Build.0 lines to skip them.

-        {E7B8C1F2-9A3D-4C2E-8B7A-6D2F3A1E4B5C}.Debug|Any CPU.Build.0 = Debug|Any CPU
-        {E7B8C1F2-9A3D-4C2E-8B7A-6D2F3A1E4B5C}.Release|Any CPU.Build.0 = Release|Any CPU
-        {08B23D8C-7AAC-4CE7-830C-4DFF9F296BFB}.Debug|Any CPU.Build.0 = Debug|Any CPU
-        {08B23D8C-7AAC-4CE7-830C-4DFF9F296BFB}.Release|Any CPU.Build.0 = Release|Any CPU
+        # Optional: omit Build.0 to exclude examples from CI solution builds
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6f1275f and 490c30e.

📒 Files selected for processing (62)
  • Mailtrap.sln (3 hunks)
  • examples/Mailtrap.Example.ContactImports/Mailtrap.Example.ContactImports.csproj (1 hunks)
  • examples/Mailtrap.Example.ContactImports/Program.cs (1 hunks)
  • examples/Mailtrap.Example.ContactImports/Properties/launchSettings.json (1 hunks)
  • examples/Mailtrap.Example.ContactImports/appsettings.json (1 hunks)
  • examples/Mailtrap.Example.ContactLists/Mailtrap.Example.ContactLists.csproj (1 hunks)
  • examples/Mailtrap.Example.ContactLists/Program.cs (1 hunks)
  • examples/Mailtrap.Example.ContactLists/Properties/launchSettings.json (1 hunks)
  • examples/Mailtrap.Example.ContactLists/appsettings.json (1 hunks)
  • src/Mailtrap.Abstractions/ContactImports/IContactsImportCollectionResource.cs (1 hunks)
  • src/Mailtrap.Abstractions/ContactImports/IContactsImportResource.cs (1 hunks)
  • src/Mailtrap.Abstractions/ContactImports/Models/ContactsImport.cs (1 hunks)
  • src/Mailtrap.Abstractions/ContactImports/Models/ContactsImportStatus.cs (1 hunks)
  • src/Mailtrap.Abstractions/ContactImports/Requests/ContactsImportRequest.cs (1 hunks)
  • src/Mailtrap.Abstractions/ContactImports/Validators/ContactsImportRequestValidator.cs (1 hunks)
  • src/Mailtrap.Abstractions/ContactLists/IContactsListCollectionResource.cs (1 hunks)
  • src/Mailtrap.Abstractions/ContactLists/IContactsListResource.cs (1 hunks)
  • src/Mailtrap.Abstractions/ContactLists/Models/ContactsList.cs (1 hunks)
  • src/Mailtrap.Abstractions/ContactLists/Requests/ContactsListRequest.cs (1 hunks)
  • src/Mailtrap.Abstractions/ContactLists/Validators/ContactsListRequestValidator.cs (1 hunks)
  • src/Mailtrap.Abstractions/Contacts/IContactCollectionResource.cs (1 hunks)
  • src/Mailtrap.Abstractions/Contacts/Requests/ContactImportRequest.cs (1 hunks)
  • src/Mailtrap.Abstractions/Contacts/Requests/ContactRequest.cs (2 hunks)
  • src/Mailtrap.Abstractions/Contacts/Requests/CreateContactRequest.cs (1 hunks)
  • src/Mailtrap.Abstractions/Contacts/Requests/UpdateContactRequest.cs (2 hunks)
  • src/Mailtrap.Abstractions/Core/Extensions/Ensure.cs (4 hunks)
  • src/Mailtrap.Abstractions/GlobalSuppressions.cs (1 hunks)
  • src/Mailtrap.Abstractions/GlobalUsings.cs (1 hunks)
  • src/Mailtrap/ContactImports/ContactsImportCollectionResource.cs (1 hunks)
  • src/Mailtrap/ContactImports/ContactsImportResource.cs (1 hunks)
  • src/Mailtrap/ContactLists/ContactsListCollectionResource.cs (1 hunks)
  • src/Mailtrap/ContactLists/ContactsListResource.cs (1 hunks)
  • src/Mailtrap/Contacts/ContactCollectionResource.cs (1 hunks)
  • src/Mailtrap/GlobalUsings.cs (1 hunks)
  • tests/Mailtrap.IntegrationTests/ContactImports/ContactImportsIntegrationTests.cs (1 hunks)
  • tests/Mailtrap.IntegrationTests/ContactImports/Create_ShouldFailValidation_WhenProvidedCollectionSizeIsInvalid.json (1 hunks)
  • tests/Mailtrap.IntegrationTests/ContactImports/Create_Success_Request.json (1 hunks)
  • tests/Mailtrap.IntegrationTests/ContactImports/Create_Success_Response.json (1 hunks)
  • tests/Mailtrap.IntegrationTests/ContactImports/GetDetails_Success.json (1 hunks)
  • tests/Mailtrap.IntegrationTests/ContactLists/ContactsListIntegrationTests.cs (1 hunks)
  • tests/Mailtrap.IntegrationTests/ContactLists/Create_Success.json (1 hunks)
  • tests/Mailtrap.IntegrationTests/ContactLists/GetAll_Success.json (1 hunks)
  • tests/Mailtrap.IntegrationTests/ContactLists/GetDetails_Success.json (1 hunks)
  • tests/Mailtrap.IntegrationTests/ContactLists/Update_Success.json (1 hunks)
  • tests/Mailtrap.IntegrationTests/Contacts/ContactsIntegrationTests.cs (6 hunks)
  • tests/Mailtrap.IntegrationTests/GlobalUsings.cs (1 hunks)
  • tests/Mailtrap.IntegrationTests/TestConstants/UrlSegmentsTestConstants.cs (1 hunks)
  • tests/Mailtrap.IntegrationTests/TestExtensions/EmailAddressHelpers.cs (1 hunks)
  • tests/Mailtrap.IntegrationTests/TestExtensions/FileHelpers.cs (1 hunks)
  • tests/Mailtrap.IntegrationTests/TestExtensions/ValidationHelpers.cs (1 hunks)
  • tests/Mailtrap.IntegrationTests/TestingMessages/TestingMessagesIntegrationTests.cs (1 hunks)
  • tests/Mailtrap.UnitTests/ContactImports/ContactsImportCollectionResourceTests.cs (1 hunks)
  • tests/Mailtrap.UnitTests/ContactImports/ContactsImportResourceTests.cs (1 hunks)
  • tests/Mailtrap.UnitTests/ContactImports/Requests/ContactsImportRequestTests.cs (1 hunks)
  • tests/Mailtrap.UnitTests/ContactLists/ContactsListCollectionResourceTests.cs (1 hunks)
  • tests/Mailtrap.UnitTests/ContactLists/ContactsListResourceTests.cs (1 hunks)
  • tests/Mailtrap.UnitTests/ContactLists/Requests/ContactsListRequestTests.cs (1 hunks)
  • tests/Mailtrap.UnitTests/Contacts/ContactCollectionResourceTests.cs (1 hunks)
  • tests/Mailtrap.UnitTests/Contacts/ContactResourceTests.cs (1 hunks)
  • tests/Mailtrap.UnitTests/Contacts/Converters/DateTimeToUnixMsNullableJsonConverterTests.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-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/ContactImports/Create_ShouldFailValidation_WhenProvidedCollectionSizeIsInvalid.json
  • tests/Mailtrap.IntegrationTests/ContactImports/Create_Success_Response.json
  • tests/Mailtrap.IntegrationTests/GlobalUsings.cs
  • tests/Mailtrap.IntegrationTests/TestingMessages/TestingMessagesIntegrationTests.cs
  • tests/Mailtrap.IntegrationTests/Contacts/ContactsIntegrationTests.cs
  • tests/Mailtrap.IntegrationTests/TestExtensions/ValidationHelpers.cs
  • tests/Mailtrap.IntegrationTests/ContactLists/ContactsListIntegrationTests.cs
  • tests/Mailtrap.IntegrationTests/ContactImports/ContactImportsIntegrationTests.cs
  • tests/Mailtrap.UnitTests/Contacts/Converters/DateTimeToUnixMsNullableJsonConverterTests.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:

  • examples/Mailtrap.Example.ContactImports/Mailtrap.Example.ContactImports.csproj
  • tests/Mailtrap.IntegrationTests/GlobalUsings.cs
  • src/Mailtrap.Abstractions/GlobalUsings.cs
  • tests/Mailtrap.IntegrationTests/Contacts/ContactsIntegrationTests.cs
  • tests/Mailtrap.UnitTests/Contacts/Converters/DateTimeToUnixMsNullableJsonConverterTests.cs
📚 Learning: 2025-09-04T08:53:30.332Z
Learnt from: vittorius
PR: railsware/mailtrap-dotnet#139
File: tests/Mailtrap.IntegrationTests/Contacts/GetDetails_Success.json:15-16
Timestamp: 2025-09-04T08:53:30.332Z
Learning: The DateTimeToTicksJsonConverter in the Mailtrap .NET client was redundant and problematic because System.Text.Json already handles DateTimeOffset serialization natively to ISO 8601 format, and other models in the codebase (TestingMessage, BillingUsagePeriod) successfully use DateTimeOffset properties without custom converters.

Applied to files:

  • examples/Mailtrap.Example.ContactImports/Mailtrap.Example.ContactImports.csproj
  • tests/Mailtrap.UnitTests/Contacts/Converters/DateTimeToUnixMsNullableJsonConverterTests.cs
📚 Learning: 2025-09-10T14:37:39.872Z
Learnt from: dr-3lo
PR: railsware/mailtrap-dotnet#142
File: src/Mailtrap/Contacts/ContactCollectionResource.cs:18-19
Timestamp: 2025-09-10T14:37:39.872Z
Learning: The Import method in ContactCollectionResource does not need explicit importId validation because this validation is already implemented in the URI model's Append method when handling long parameters.

Applied to files:

  • src/Mailtrap/Contacts/ContactCollectionResource.cs
  • tests/Mailtrap.UnitTests/ContactImports/ContactsImportResourceTests.cs
  • tests/Mailtrap.UnitTests/Contacts/ContactCollectionResourceTests.cs
  • tests/Mailtrap.UnitTests/ContactImports/ContactsImportCollectionResourceTests.cs
  • src/Mailtrap/ContactImports/ContactsImportResource.cs
  • src/Mailtrap.Abstractions/ContactImports/IContactsImportCollectionResource.cs
  • tests/Mailtrap.IntegrationTests/ContactImports/ContactImportsIntegrationTests.cs
  • src/Mailtrap/ContactImports/ContactsImportCollectionResource.cs
  • src/Mailtrap.Abstractions/Contacts/IContactCollectionResource.cs
  • src/Mailtrap.Abstractions/ContactImports/Requests/ContactsImportRequest.cs
📚 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.IntegrationTests/GlobalUsings.cs
  • tests/Mailtrap.UnitTests/GlobalUsings.cs
  • src/Mailtrap.Abstractions/GlobalUsings.cs
  • examples/Mailtrap.Example.ContactImports/Program.cs
  • src/Mailtrap/GlobalUsings.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/ContactLists/Validators/ContactsListRequestValidator.cs
  • tests/Mailtrap.UnitTests/ContactImports/Requests/ContactsImportRequestTests.cs
  • src/Mailtrap.Abstractions/Contacts/Requests/ContactRequest.cs
  • src/Mailtrap.Abstractions/ContactLists/Requests/ContactsListRequest.cs
  • src/Mailtrap.Abstractions/ContactImports/Validators/ContactsImportRequestValidator.cs
  • src/Mailtrap.Abstractions/ContactImports/Requests/ContactsImportRequest.cs
  • src/Mailtrap.Abstractions/Contacts/Requests/ContactImportRequest.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: The Mailtrap .NET client uses default JSON serialization for DateTimeOffset properties without explicit JsonConverter attributes, as seen in models like TestingMessage. DateTime fields should not use the DateTimeToTicksJsonConverter since the API returns Unix epoch milliseconds, not .NET ticks.

Applied to files:

  • tests/Mailtrap.UnitTests/Contacts/Converters/DateTimeToUnixMsNullableJsonConverterTests.cs
🧬 Code graph analysis (33)
tests/Mailtrap.UnitTests/ContactLists/ContactsListResourceTests.cs (2)
tests/Mailtrap.UnitTests/TestConstants/UrlSegmentsTestConstants.cs (1)
  • UrlSegmentsTestConstants (4-20)
src/Mailtrap/ContactLists/ContactsListResource.cs (2)
  • ContactsListResource (6-16)
  • ContactsListResource (8-9)
src/Mailtrap/Contacts/ContactCollectionResource.cs (5)
src/Mailtrap.Abstractions/Contacts/IContactCollectionResource.cs (4)
  • IContactsImportCollectionResource (17-17)
  • IContactsImportResource (34-34)
  • IContactsListCollectionResource (43-43)
  • IContactsListResource (60-60)
src/Mailtrap/ContactImports/ContactsImportCollectionResource.cs (2)
  • ContactsImportCollectionResource (6-13)
  • ContactsImportCollectionResource (8-9)
src/Mailtrap/ContactImports/ContactsImportResource.cs (2)
  • ContactsImportResource (6-13)
  • ContactsImportResource (8-9)
src/Mailtrap/ContactLists/ContactsListCollectionResource.cs (2)
  • ContactsListCollectionResource (6-16)
  • ContactsListCollectionResource (8-9)
src/Mailtrap/ContactLists/ContactsListResource.cs (2)
  • ContactsListResource (6-16)
  • ContactsListResource (8-9)
src/Mailtrap/ContactLists/ContactsListResource.cs (2)
src/Mailtrap/Contacts/ContactCollectionResource.cs (3)
  • IContactsListResource (25-26)
  • Task (28-29)
  • Task (31-32)
src/Mailtrap.Abstractions/ContactLists/IContactsListResource.cs (3)
  • Task (19-19)
  • Task (36-36)
  • Task (56-56)
tests/Mailtrap.UnitTests/ContactImports/ContactsImportResourceTests.cs (4)
tests/Mailtrap.UnitTests/ContactImports/Requests/ContactsImportRequestTests.cs (5)
  • TestFixture (4-103)
  • Test (7-13)
  • Test (15-21)
  • Test (23-34)
  • Test (37-53)
tests/Mailtrap.UnitTests/ContactImports/ContactsImportCollectionResourceTests.cs (1)
  • TestFixture (4-52)
tests/Mailtrap.UnitTests/Contacts/ContactResourceTests.cs (1)
  • TestFixture (4-51)
tests/Mailtrap.UnitTests/TestConstants/UrlSegmentsTestConstants.cs (1)
  • UrlSegmentsTestConstants (4-20)
tests/Mailtrap.UnitTests/Contacts/ContactCollectionResourceTests.cs (4)
tests/Mailtrap.UnitTests/TestExtensions/ResourceValidator.cs (2)
  • ResourceValidator (4-16)
  • Validate (6-15)
src/Mailtrap.Abstractions/Contacts/IContactCollectionResource.cs (4)
  • IContactsImportCollectionResource (17-17)
  • IContactsImportResource (34-34)
  • IContactsListCollectionResource (43-43)
  • IContactsListResource (60-60)
src/Mailtrap/Contacts/ContactCollectionResource.cs (4)
  • IContactsImportCollectionResource (16-17)
  • IContactsImportResource (19-20)
  • IContactsListCollectionResource (22-23)
  • IContactsListResource (25-26)
tests/Mailtrap.UnitTests/TestConstants/UrlSegmentsTestConstants.cs (1)
  • UrlSegmentsTestConstants (4-20)
tests/Mailtrap.UnitTests/ContactLists/Requests/ContactsListRequestTests.cs (1)
src/Mailtrap.Abstractions/ContactLists/Requests/ContactsListRequest.cs (2)
  • ContactsListRequest (34-39)
  • ContactsListRequest (44-44)
src/Mailtrap.Abstractions/ContactLists/Validators/ContactsListRequestValidator.cs (1)
src/Mailtrap.Abstractions/ContactLists/Requests/ContactsListRequest.cs (2)
  • ContactsListRequest (34-39)
  • ContactsListRequest (44-44)
tests/Mailtrap.UnitTests/ContactImports/ContactsImportCollectionResourceTests.cs (4)
tests/Mailtrap.UnitTests/ContactImports/ContactsImportResourceTests.cs (1)
  • TestFixture (4-52)
tests/Mailtrap.UnitTests/Contacts/ContactResourceTests.cs (1)
  • TestFixture (4-51)
tests/Mailtrap.UnitTests/TestConstants/UrlSegmentsTestConstants.cs (1)
  • UrlSegmentsTestConstants (4-20)
src/Mailtrap/ContactImports/ContactsImportCollectionResource.cs (2)
  • ContactsImportCollectionResource (6-13)
  • ContactsImportCollectionResource (8-9)
src/Mailtrap.Abstractions/ContactLists/IContactsListCollectionResource.cs (4)
src/Mailtrap.Abstractions/Contacts/IContactCollectionResource.cs (3)
  • IContactsListCollectionResource (43-43)
  • Task (73-73)
  • Task (90-90)
src/Mailtrap/Contacts/ContactCollectionResource.cs (3)
  • IContactsListCollectionResource (22-23)
  • Task (28-29)
  • Task (31-32)
src/Mailtrap/ContactLists/ContactsListCollectionResource.cs (2)
  • Task (11-12)
  • Task (14-15)
src/Mailtrap.Abstractions/ContactLists/Requests/ContactsListRequest.cs (2)
  • ContactsListRequest (34-39)
  • ContactsListRequest (44-44)
tests/Mailtrap.UnitTests/ContactImports/Requests/ContactsImportRequestTests.cs (2)
src/Mailtrap.Abstractions/ContactImports/Requests/ContactsImportRequest.cs (2)
  • ContactsImportRequest (39-47)
  • ContactsImportRequest (52-52)
src/Mailtrap.Abstractions/Contacts/Requests/ContactImportRequest.cs (2)
  • ContactImportRequest (31-31)
  • ContactImportRequest (36-36)
src/Mailtrap.Abstractions/Core/Extensions/Ensure.cs (2)
src/Mailtrap.Abstractions/Core/Models/StringEnum.cs (2)
  • T (66-72)
  • T (86-97)
src/Mailtrap/Core/Extensions/HttpContentExtensions.cs (1)
  • T (28-35)
src/Mailtrap.Abstractions/Contacts/Requests/UpdateContactRequest.cs (2)
src/Mailtrap.Abstractions/Contacts/Requests/ContactImportRequest.cs (2)
  • ContactImportRequest (31-31)
  • ContactImportRequest (36-36)
tests/Mailtrap.UnitTests/ContactImports/Requests/ContactsImportRequestTests.cs (1)
  • ContactImportRequest (95-102)
tests/Mailtrap.UnitTests/ContactLists/ContactsListCollectionResourceTests.cs (2)
tests/Mailtrap.UnitTests/TestConstants/UrlSegmentsTestConstants.cs (1)
  • UrlSegmentsTestConstants (4-20)
src/Mailtrap/ContactLists/ContactsListCollectionResource.cs (2)
  • ContactsListCollectionResource (6-16)
  • ContactsListCollectionResource (8-9)
tests/Mailtrap.IntegrationTests/Contacts/ContactsIntegrationTests.cs (4)
tests/Mailtrap.IntegrationTests/TestExtensions/EmailAddressHelpers.cs (1)
  • NextEmail (14-49)
src/Mailtrap.Abstractions/Contacts/Requests/CreateContactRequest.cs (2)
  • CreateContactRequest (19-19)
  • CreateContactRequest (24-24)
tests/Mailtrap.IntegrationTests/TestExtensions/ValidationHelpers.cs (1)
  • ShouldBeEquivalentToContactResponse (25-40)
src/Mailtrap.Abstractions/Contacts/Requests/UpdateContactRequest.cs (2)
  • UpdateContactRequest (19-19)
  • UpdateContactRequest (24-24)
examples/Mailtrap.Example.ContactImports/Program.cs (4)
src/Mailtrap.Abstractions/Contacts/IContactCollectionResource.cs (2)
  • IContactsImportCollectionResource (17-17)
  • IContactsImportResource (34-34)
src/Mailtrap/Contacts/ContactCollectionResource.cs (2)
  • IContactsImportCollectionResource (16-17)
  • IContactsImportResource (19-20)
src/Mailtrap.Abstractions/Contacts/Requests/ContactImportRequest.cs (2)
  • ContactImportRequest (31-31)
  • ContactImportRequest (36-36)
src/Mailtrap.Abstractions/ContactImports/Requests/ContactsImportRequest.cs (2)
  • ContactsImportRequest (39-47)
  • ContactsImportRequest (52-52)
src/Mailtrap.Abstractions/ContactImports/IContactsImportResource.cs (5)
src/Mailtrap.Abstractions/Contacts/IContactCollectionResource.cs (3)
  • IContactsImportResource (34-34)
  • Task (73-73)
  • Task (90-90)
src/Mailtrap/Contacts/ContactCollectionResource.cs (3)
  • IContactsImportResource (19-20)
  • Task (28-29)
  • Task (31-32)
src/Mailtrap.Abstractions/ContactImports/IContactsImportCollectionResource.cs (1)
  • Task (28-28)
src/Mailtrap/ContactImports/ContactsImportCollectionResource.cs (1)
  • Task (11-12)
src/Mailtrap/ContactImports/ContactsImportResource.cs (1)
  • Task (11-12)
src/Mailtrap.Abstractions/ContactImports/Models/ContactsImportStatus.cs (1)
src/Mailtrap.Abstractions/Core/Models/StringEnum.cs (1)
  • StringEnum (41-49)
tests/Mailtrap.IntegrationTests/TestExtensions/ValidationHelpers.cs (2)
tests/Mailtrap.IntegrationTests/TestExtensions/FileHelpers.cs (2)
  • Task (6-14)
  • Task (16-28)
src/Mailtrap/Configuration/MailtrapClientOptions.cs (1)
  • JsonSerializerOptions (148-154)
src/Mailtrap.Abstractions/ContactLists/IContactsListResource.cs (3)
src/Mailtrap.Abstractions/Contacts/IContactCollectionResource.cs (3)
  • IContactsListResource (60-60)
  • Task (73-73)
  • Task (90-90)
src/Mailtrap/Contacts/ContactCollectionResource.cs (3)
  • IContactsListResource (25-26)
  • Task (28-29)
  • Task (31-32)
src/Mailtrap/ContactLists/ContactsListResource.cs (3)
  • Task (10-11)
  • Task (12-13)
  • Task (14-15)
tests/Mailtrap.IntegrationTests/ContactLists/ContactsListIntegrationTests.cs (16)
tests/Mailtrap.IntegrationTests/ContactImports/ContactImportsIntegrationTests.cs (5)
  • Test (33-77)
  • Test (79-122)
  • Test (124-167)
  • Test (169-212)
  • Test (214-253)
tests/Mailtrap.IntegrationTests/Contacts/ContactsIntegrationTests.cs (7)
  • Test (33-71)
  • Test (73-115)
  • Test (117-154)
  • Test (156-195)
  • Test (197-240)
  • Test (242-280)
  • Test (282-315)
src/Mailtrap/Configuration/MailtrapClientOptions.cs (1)
  • JsonSerializerOptions (148-154)
tests/Mailtrap.IntegrationTests/TestConstants/UrlSegmentsTestConstants.cs (1)
  • UrlSegmentsTestConstants (4-23)
src/Mailtrap.Abstractions/ContactLists/IContactsListCollectionResource.cs (2)
  • Task (19-19)
  • Task (36-36)
src/Mailtrap.Abstractions/Contacts/IContactCollectionResource.cs (2)
  • Task (73-73)
  • Task (90-90)
tests/Mailtrap.IntegrationTests/TestExtensions/ValidationHelpers.cs (1)
  • Task (6-17)
src/Mailtrap.Abstractions/ContactLists/IContactsListResource.cs (3)
  • Task (19-19)
  • Task (36-36)
  • Task (56-56)
src/Mailtrap/ContactLists/ContactsListCollectionResource.cs (2)
  • Task (11-12)
  • Task (14-15)
src/Mailtrap/ContactLists/ContactsListResource.cs (3)
  • Task (10-11)
  • Task (12-13)
  • Task (14-15)
src/Mailtrap/Contacts/ContactCollectionResource.cs (2)
  • Task (28-29)
  • Task (31-32)
tests/Mailtrap.IntegrationTests/TestExtensions/FileHelpers.cs (1)
  • Task (6-14)
src/Mailtrap/Core/Constants/MimeTypes.cs (2)
  • MimeTypes (4-19)
  • Application (6-11)
src/Mailtrap/Core/Constants/HeaderValues.cs (1)
  • HeaderValues (7-12)
src/Mailtrap.Abstractions/ContactLists/Requests/ContactsListRequest.cs (2)
  • ContactsListRequest (34-39)
  • ContactsListRequest (44-44)
src/Mailtrap/Core/Extensions/HttpMethodEx.cs (1)
  • HttpMethodEx (7-10)
src/Mailtrap/ContactImports/ContactsImportResource.cs (3)
src/Mailtrap.Abstractions/Contacts/IContactCollectionResource.cs (3)
  • IContactsImportResource (34-34)
  • Task (73-73)
  • Task (90-90)
src/Mailtrap/Contacts/ContactCollectionResource.cs (3)
  • IContactsImportResource (19-20)
  • Task (28-29)
  • Task (31-32)
src/Mailtrap.Abstractions/ContactImports/IContactsImportResource.cs (1)
  • Task (19-19)
src/Mailtrap.Abstractions/ContactImports/IContactsImportCollectionResource.cs (4)
src/Mailtrap.Abstractions/Contacts/IContactCollectionResource.cs (3)
  • IContactsImportCollectionResource (17-17)
  • Task (73-73)
  • Task (90-90)
src/Mailtrap/Contacts/ContactCollectionResource.cs (3)
  • IContactsImportCollectionResource (16-17)
  • Task (28-29)
  • Task (31-32)
src/Mailtrap/ContactImports/ContactsImportCollectionResource.cs (1)
  • Task (11-12)
src/Mailtrap.Abstractions/ContactImports/Requests/ContactsImportRequest.cs (2)
  • ContactsImportRequest (39-47)
  • ContactsImportRequest (52-52)
tests/Mailtrap.IntegrationTests/ContactImports/ContactImportsIntegrationTests.cs (9)
tests/Mailtrap.UnitTests/Contacts/ContactCollectionResourceTests.cs (1)
  • TestFixture (4-143)
tests/Mailtrap.UnitTests/ContactImports/ContactsImportCollectionResourceTests.cs (4)
  • TestFixture (4-52)
  • Test (19-27)
  • Test (29-37)
  • Test (39-47)
src/Mailtrap/Configuration/MailtrapClientOptions.cs (1)
  • JsonSerializerOptions (148-154)
tests/Mailtrap.IntegrationTests/TestConstants/UrlSegmentsTestConstants.cs (1)
  • UrlSegmentsTestConstants (4-23)
tests/Mailtrap.IntegrationTests/TestExtensions/ValidationHelpers.cs (1)
  • Task (6-17)
tests/Mailtrap.IntegrationTests/TestExtensions/FileHelpers.cs (2)
  • Task (6-14)
  • Task (16-28)
src/Mailtrap.Abstractions/ContactImports/Requests/ContactsImportRequest.cs (2)
  • ContactsImportRequest (39-47)
  • ContactsImportRequest (52-52)
src/Mailtrap/Core/Constants/MimeTypes.cs (2)
  • MimeTypes (4-19)
  • Application (6-11)
src/Mailtrap/Core/Constants/HeaderValues.cs (1)
  • HeaderValues (7-12)
src/Mailtrap/ContactImports/ContactsImportCollectionResource.cs (5)
tests/Mailtrap.UnitTests/ContactImports/ContactsImportCollectionResourceTests.cs (1)
  • ContactsImportCollectionResource (51-51)
src/Mailtrap/Contacts/ContactCollectionResource.cs (3)
  • IContactsImportCollectionResource (16-17)
  • Task (28-29)
  • Task (31-32)
src/Mailtrap.Abstractions/ContactImports/IContactsImportCollectionResource.cs (1)
  • Task (28-28)
src/Mailtrap/ContactImports/ContactsImportResource.cs (1)
  • Task (11-12)
src/Mailtrap.Abstractions/ContactImports/Requests/ContactsImportRequest.cs (2)
  • ContactsImportRequest (39-47)
  • ContactsImportRequest (52-52)
examples/Mailtrap.Example.ContactLists/Program.cs (3)
src/Mailtrap.Abstractions/Contacts/IContactCollectionResource.cs (2)
  • IContactsListCollectionResource (43-43)
  • IContactsListResource (60-60)
src/Mailtrap/Contacts/ContactCollectionResource.cs (2)
  • IContactsListCollectionResource (22-23)
  • IContactsListResource (25-26)
src/Mailtrap.Abstractions/ContactLists/Requests/ContactsListRequest.cs (2)
  • ContactsListRequest (34-39)
  • ContactsListRequest (44-44)
src/Mailtrap.Abstractions/ContactLists/Requests/ContactsListRequest.cs (2)
src/Mailtrap.Abstractions/Core/Extensions/Ensure.cs (1)
  • Ensure (9-106)
src/Mailtrap.Abstractions/ContactLists/Validators/ContactsListRequestValidator.cs (2)
  • ContactsListRequestValidator (8-22)
  • ContactsListRequestValidator (18-21)
src/Mailtrap/ContactLists/ContactsListCollectionResource.cs (5)
tests/Mailtrap.UnitTests/ContactLists/ContactsListCollectionResourceTests.cs (1)
  • ContactsListCollectionResource (51-51)
src/Mailtrap/Contacts/ContactCollectionResource.cs (3)
  • IContactsListCollectionResource (22-23)
  • Task (28-29)
  • Task (31-32)
src/Mailtrap.Abstractions/ContactLists/IContactsListCollectionResource.cs (2)
  • Task (19-19)
  • Task (36-36)
src/Mailtrap/ContactLists/ContactsListResource.cs (3)
  • Task (10-11)
  • Task (12-13)
  • Task (14-15)
src/Mailtrap.Abstractions/ContactLists/Requests/ContactsListRequest.cs (2)
  • ContactsListRequest (34-39)
  • ContactsListRequest (44-44)
src/Mailtrap.Abstractions/Contacts/IContactCollectionResource.cs (3)
src/Mailtrap/Accounts/AccountResource.cs (1)
  • IContactCollectionResource (56-57)
src/Mailtrap.Abstractions/Accounts/IAccountResource.cs (1)
  • IContactCollectionResource (143-143)
src/Mailtrap/Contacts/ContactCollectionResource.cs (4)
  • IContactsImportCollectionResource (16-17)
  • IContactsImportResource (19-20)
  • IContactsListCollectionResource (22-23)
  • IContactsListResource (25-26)
tests/Mailtrap.UnitTests/Contacts/Converters/DateTimeToUnixMsNullableJsonConverterTests.cs (2)
src/Mailtrap/Configuration/MailtrapClientOptions.cs (1)
  • JsonSerializerOptions (148-154)
src/Mailtrap.Abstractions/Contacts/Converters/DateTimeToUnixMsJsonConverter.cs (2)
  • DateTimeToUnixMsNullableJsonConverter (6-34)
  • DateTimeOffset (8-22)
src/Mailtrap.Abstractions/ContactImports/Validators/ContactsImportRequestValidator.cs (1)
src/Mailtrap.Abstractions/ContactImports/Requests/ContactsImportRequest.cs (2)
  • ContactsImportRequest (39-47)
  • ContactsImportRequest (52-52)
src/Mailtrap.Abstractions/ContactImports/Requests/ContactsImportRequest.cs (5)
src/Mailtrap.Abstractions/Contacts/Requests/ContactImportRequest.cs (2)
  • ContactImportRequest (31-31)
  • ContactImportRequest (36-36)
tests/Mailtrap.UnitTests/ContactImports/Requests/ContactsImportRequestTests.cs (1)
  • ContactImportRequest (95-102)
src/Mailtrap.Abstractions/Core/Extensions/Ensure.cs (3)
  • Ensure (9-106)
  • NotNullOrEmpty (42-57)
  • NotNullOrEmpty (66-81)
src/Mailtrap.Abstractions/Contacts/Requests/ContactRequest.cs (1)
  • ValidationResult (59-64)
src/Mailtrap.Abstractions/ContactImports/Validators/ContactsImportRequestValidator.cs (2)
  • ContactsImportRequestValidator (8-31)
  • ContactsImportRequestValidator (20-30)
src/Mailtrap.Abstractions/Contacts/Requests/ContactImportRequest.cs (2)
tests/Mailtrap.UnitTests/ContactImports/Requests/ContactsImportRequestTests.cs (1)
  • ContactImportRequest (95-102)
src/Mailtrap.Abstractions/Contacts/Requests/ContactRequest.cs (2)
  • ContactRequest (45-50)
  • ContactRequest (55-55)
tests/Mailtrap.IntegrationTests/TestExtensions/FileHelpers.cs (4)
tests/Mailtrap.IntegrationTests/TestExtensions/ValidationHelpers.cs (1)
  • Task (6-17)
src/Mailtrap.Abstractions/Core/Extensions/Ensure.cs (1)
  • Ensure (9-106)
tests/Mailtrap.IntegrationTests/ContactImports/ContactImportsIntegrationTests.cs (5)
  • Test (33-77)
  • Test (79-122)
  • Test (124-167)
  • Test (169-212)
  • Test (214-253)
tests/Mailtrap.IntegrationTests/Contacts/ContactsIntegrationTests.cs (7)
  • Test (33-71)
  • Test (73-115)
  • Test (117-154)
  • Test (156-195)
  • Test (197-240)
  • Test (242-280)
  • Test (282-315)

@dr-3lo dr-3lo changed the base branch from main to feature/125-Contact-Imports September 15, 2025 12:08
- XML Doc corrections
- fix typos in tests names
…or selection explicit and avoid ambiguity with parametrized ctor
Copy link
Contributor

@mklocek mklocek left a comment

Choose a reason for hiding this comment

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

👍

@dr-3lo
Copy link
Collaborator Author

dr-3lo commented Sep 15, 2025

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Sep 15, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

@coderabbitai coderabbitai bot left a 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 (5)
src/Mailtrap.Abstractions/Contacts/Requests/ContactRequest.cs (2)

23-26: Clarify remark on System.Text.Json behavior for object values

Tighten the docs so consumers know exactly what to expect from object-typed values in Fields.

Apply this doc-only tweak:

-    /// <remarks>
-    /// object-typed values may deserialize numbers as JsonElement
-    /// </remarks>
+    /// <remarks>
+    /// With System.Text.Json, object-typed values deserialize as:
+    /// numbers/objects/arrays -> JsonElement; strings -> string; booleans -> bool; null -> null.
+    /// Consumers should handle JsonElement when reading numeric or composite values.
+    /// </remarks>

59-60: Decide whether deserialization should enforce constructor invariants — repo currently uses paramless [JsonConstructor]

Found [JsonConstructor] on parameterless ctors in:
src/Mailtrap.Abstractions/Contacts/Requests/ContactImportRequest.cs,
src/Mailtrap.Abstractions/Contacts/Requests/ContactRequest.cs,
src/Mailtrap.Abstractions/Contacts/Requests/CreateContactRequest.cs,
src/Mailtrap.Abstractions/Contacts/Requests/UpdateContactRequest.cs,
src/Mailtrap.Abstractions/ContactLists/Requests/ContactsListRequest.cs,
src/Mailtrap.Abstractions/ContactImports/Requests/ContactsImportRequest.cs.

Action: keep the attribute on the parameterless ctors (validation deferred to validators) or move [JsonConstructor] to the parameterized ctor in ContactRequest and make the same change across the other request types to preserve consistency and enable constructor-level invariants (e.g., non-empty Email).

tests/Mailtrap.UnitTests/ContactLists/Requests/ContactsListRequestTests.cs (3)

1-1: Strip BOM/invisible char before namespace.

There's a leading BOM/zero-width char before the namespace. Remove to avoid noisy diffs and tooling hiccups.


23-34: Prefer deterministic data in unit tests.

Random strings can introduce flakiness with future constraints. Use a fixed string.

Apply this diff:

-        var name = TestContext.CurrentContext.Random.GetString(5);
+        var name = new string('a', 5);

36-48: Strengthen validation test and simplify parameterization.

Use TestCase over Values here, avoid randomness, and add positive boundary tests (1 and 255) to lock invariants.

Apply this diff:

-    [Test]
-    public void Validate_ShouldFail_WhenProvidedNameLengthIsInvalid([Values(256)] int length)
+    [TestCase(256)]
+    public void Validate_ShouldFail_WhenProvidedNameLengthIsInvalid(int length)
@@
-        var name = TestContext.CurrentContext.Random.GetString(length);
+        var name = new string('a', length);

Add these tests:

[TestCase(1)]
[TestCase(255)]
public void Validate_ShouldPass_WhenProvidedNameLengthIsValid(int length)
{
    var name = new string('a', length);
    var request = new ContactsListRequest(name);

    var result = request.Validate();

    result.IsValid.Should().BeTrue();
}

Optional: if MailtrapValidationResult exposes error members, assert it flags Name length:

// Example; adjust to your result shape
result.Errors.Should().ContainSingle(e => e.PropertyName == nameof(ContactsListRequest.Name));
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 490c30e and 3a91146.

📒 Files selected for processing (11)
  • src/Mailtrap.Abstractions/ContactImports/IContactsImportCollectionResource.cs (2 hunks)
  • src/Mailtrap.Abstractions/ContactImports/Requests/ContactsImportRequest.cs (3 hunks)
  • src/Mailtrap.Abstractions/ContactImports/Validators/ContactsImportRequestValidator.cs (1 hunks)
  • src/Mailtrap.Abstractions/ContactLists/IContactsListResource.cs (1 hunks)
  • src/Mailtrap.Abstractions/ContactLists/Requests/ContactsListRequest.cs (1 hunks)
  • src/Mailtrap.Abstractions/Contacts/Requests/ContactImportRequest.cs (1 hunks)
  • src/Mailtrap.Abstractions/Contacts/Requests/ContactRequest.cs (2 hunks)
  • src/Mailtrap.Abstractions/Contacts/Requests/CreateContactRequest.cs (1 hunks)
  • src/Mailtrap.Abstractions/Contacts/Requests/UpdateContactRequest.cs (1 hunks)
  • tests/Mailtrap.IntegrationTests/TestExtensions/ValidationHelpers.cs (1 hunks)
  • tests/Mailtrap.UnitTests/ContactLists/Requests/ContactsListRequestTests.cs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (9)
  • tests/Mailtrap.IntegrationTests/TestExtensions/ValidationHelpers.cs
  • src/Mailtrap.Abstractions/ContactLists/IContactsListResource.cs
  • src/Mailtrap.Abstractions/ContactImports/Validators/ContactsImportRequestValidator.cs
  • src/Mailtrap.Abstractions/ContactLists/Requests/ContactsListRequest.cs
  • src/Mailtrap.Abstractions/Contacts/Requests/CreateContactRequest.cs
  • src/Mailtrap.Abstractions/Contacts/Requests/ContactImportRequest.cs
  • src/Mailtrap.Abstractions/Contacts/Requests/UpdateContactRequest.cs
  • src/Mailtrap.Abstractions/ContactImports/Requests/ContactsImportRequest.cs
  • src/Mailtrap.Abstractions/ContactImports/IContactsImportCollectionResource.cs
🔇 Additional comments (3)
tests/Mailtrap.UnitTests/ContactLists/Requests/ContactsListRequestTests.cs (3)

7-13: LGTM: null-argument guard test.

This accurately asserts constructor null handling.


5-6: Keep the fixture internal — match repo convention.
The codebase declares test fixtures as internal sealed across tests/, so changing this single class to public would be inconsistent.

Likely an incorrect or invalid review comment.


15-21: Keep ArgumentNullException — Ensure.NotNullOrEmpty intentionally throws ArgumentNullException for empty strings.

Ensure.NotNullOrEmpty (src/Mailtrap.Abstractions/Core/Extensions/Ensure.cs) and its unit tests (tests/Mailtrap.UnitTests/Core/Extensions/EnsureTests.cs) expect/throw ArgumentNullException for both null and empty; leave the test as-is.

Likely an incorrect or invalid review comment.

/// The import process runs asynchronously - use the returned
/// import ID to check the status and results.
/// List all contacts with details into <paramref name="request"/>.
/// Provide the contacts to import in the <paramref name="request"/>.

Choose a reason for hiding this comment

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

👍

Base automatically changed from feature/125-Contact-Imports to main September 19, 2025 13:45
# Conflicts:
#	Mailtrap.sln
#	src/Mailtrap.Abstractions/ContactImports/IContactsImportCollectionResource.cs
#	src/Mailtrap.Abstractions/ContactImports/Requests/ContactsImportRequest.cs
#	src/Mailtrap.Abstractions/ContactImports/Validators/ContactsImportRequestValidator.cs
#	src/Mailtrap.Abstractions/Contacts/IContactCollectionResource.cs
#	src/Mailtrap.Abstractions/Contacts/Requests/ContactImportRequest.cs
#	src/Mailtrap.Abstractions/Contacts/Requests/ContactRequest.cs
#	src/Mailtrap.Abstractions/Contacts/Requests/CreateContactRequest.cs
#	src/Mailtrap.Abstractions/Contacts/Requests/UpdateContactRequest.cs
#	src/Mailtrap.Abstractions/GlobalUsings.cs
#	src/Mailtrap/Contacts/ContactCollectionResource.cs
#	src/Mailtrap/GlobalUsings.cs
#	tests/Mailtrap.IntegrationTests/ContactImports/ContactImportsIntegrationTests.cs
#	tests/Mailtrap.IntegrationTests/GlobalUsings.cs
#	tests/Mailtrap.IntegrationTests/TestConstants/UrlSegmentsTestConstants.cs
#	tests/Mailtrap.IntegrationTests/TestExtensions/EmailAddressHelpers.cs
#	tests/Mailtrap.UnitTests/GlobalUsings.cs
#	tests/Mailtrap.UnitTests/TestConstants/UrlSegmentsTestConstants.cs
Copy link

@coderabbitai coderabbitai bot left a 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 (1)
examples/Mailtrap.Example.ContactImports/Mailtrap.Example.ContactImports.csproj (1)

4-4: Remove redundant System.Text.Json PackageReference from the example project

Project inherits net9.0 (build/mailtrap-example.props) and the repo centrally pins System.Text.Json (Directory.Packages.props → 9.0.9). Remove the per-project reference in examples/Mailtrap.Example.ContactImports/Mailtrap.Example.ContactImports.csproj.

   <ItemGroup>
-    <PackageReference Include="System.Text.Json" />
   </ItemGroup>
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3a91146 and e793b1b.

📒 Files selected for processing (2)
  • examples/Mailtrap.Example.ContactImports/Mailtrap.Example.ContactImports.csproj (1 hunks)
  • examples/Mailtrap.Example.ContactLists/Mailtrap.Example.ContactLists.csproj (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • examples/Mailtrap.Example.ContactLists/Mailtrap.Example.ContactLists.csproj
🧰 Additional context used
🧠 Learnings (1)
📚 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:

  • examples/Mailtrap.Example.ContactImports/Mailtrap.Example.ContactImports.csproj
🔇 Additional comments (1)
examples/Mailtrap.Example.ContactImports/Mailtrap.Example.ContactImports.csproj (1)

3-4: Central package management configured — no action needed.

Directory.Packages.props defines PackageVersion entries for Microsoft.Extensions.Http (line 9, Version="9.0.9") and System.Text.Json (line 14, Version="9.0.9"), so the PackageReference entries in examples/Mailtrap.Example.ContactImports/Mailtrap.Example.ContactImports.csproj may omit Version.

@dr-3lo dr-3lo merged commit dfcb42e into main Sep 19, 2025
3 checks passed
@dr-3lo dr-3lo deleted the feature/124-Contact-Lists branch September 19, 2025 14:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add possibility to compare expected response with actual one in Contacts Integration Tests Contacts API: Lists

5 participants