Skip to content

Expand Cosmos Emulator tests and harden read extension validation - #18

Draft
xperiandri with Copilot wants to merge 34 commits into
mainfrom
copilot/add-integration-tests-cosmos-emulator-again
Draft

Expand Cosmos Emulator tests and harden read extension validation#18
xperiandri with Copilot wants to merge 34 commits into
mainfrom
copilot/add-integration-tests-cosmos-emulator-again

Conversation

Copilot AI commented May 23, 2026

Copy link
Copy Markdown

This PR expands Cosmos Emulator integration coverage and incorporates review-driven fixes in both tests and read extension behavior.

Changes Made

  • Expanded and reorganized operation/read integration tests with scenario-based seeding using DatabaseTestApplicationFactory derivatives (SingleItemScenario, MultipleItemsScenario).
  • Refactored integration test infrastructure to support generic IntegrationTestBase<'DatabaseTestApplicationFactory> / OperationTestBase<'DatabaseTestApplicationFactory> patterns.
  • Added shared TestCategories constants and applied explicit TestCategory attributes across test classes.
  • Updated IsNotDeletedAsync in Cosmos.fs:
    • changed deletedFieldName to non-nullable string,
    • kept an explicit runtime nullArg guard,
    • retained strict identifier validation for invalid field names,
    • corrected requestOptions parameter naming.
  • Added XML <exception> documentation for methods that throw in Cosmos.fs (IsNotDeletedAsync, AddPreTriggers, AddPostTriggers).
  • Expanded read extension integration coverage for deleted-field-name validation and behavior, including:
    • null/empty/whitespace invalid inputs,
    • invalid start and invalid character cases,
    • valid underscore and digit-in-body field names,
    • verification that setting a valid digit-containing deleted marker changes IsNotDeletedAsync result as expected.
  • Formatted updated F# files with Fantomas.

Validation

  • dotnet build FSharp.Azure.Cosmos.slnx
  • dotnet test FSharp.Azure.Cosmos.slnx
  • dotnet test tests/Cosmos.Tests/FSharp.Azure.Cosmos.Tests.fsproj
  • dotnet test tests/Cosmos.Tests/FSharp.Azure.Cosmos.Tests.fsproj --filter "FullyQualifiedName~ReadExtensionsIntegrationTests"
  • Final automated validation checks passed (code review + security scan).

Copilot AI linked an issue May 23, 2026 that may be closed by this pull request
Copilot AI changed the title [WIP] Add integration tests against Cosmos Emulator Add Cosmos Emulator integration test foundation and scoped scenario plan May 23, 2026
Copilot AI requested a review from xperiandri May 23, 2026 18:31

@xperiandri xperiandri left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Fix and format with Fantomas according to your instructions

Comment thread tests/Cosmos.Tests/IntegrationInfrastructure.fs Outdated
Comment thread tests/Cosmos.Tests/IntegrationInfrastructure.fs Outdated
Comment thread tests/Cosmos.Tests/IntegrationInfrastructure.fs Outdated
Comment thread tests/Cosmos.Tests/IntegrationTestPlan.fs Outdated
Comment thread tests/Cosmos.Tests/IntegrationInfrastructure.fs Outdated
Copilot AI requested a review from xperiandri May 24, 2026 00:16
Copilot AI changed the title Add Cosmos Emulator integration test foundation and scoped scenario plan Add Cosmos Emulator integration tests for core operations May 24, 2026
Comment thread tests/Cosmos.Tests/Tests.fs Outdated
Copilot AI requested a review from xperiandri May 24, 2026 01:22
Copilot AI changed the title Add Cosmos Emulator integration tests for core operations Expand Cosmos Emulator tests for operations, read extensions, and builders May 24, 2026
@xperiandri
xperiandri force-pushed the copilot/add-integration-tests-cosmos-emulator-again branch from 542f3fc to d5b9617 Compare May 24, 2026 14:48
Copilot AI and others added 15 commits May 25, 2026 00:56
Co-authored-by: Andrii Chebukin <XperiAndri@Outlook.com>
Agent-Logs-Url: https://github.com/fsprojects/FSharp.Azure.Cosmos/sessions/b2eda2fa-a0cb-4604-b8ca-51bd73075963

Co-authored-by: xperiandri <2365592+xperiandri@users.noreply.github.com>
@xperiandri
xperiandri force-pushed the copilot/add-integration-tests-cosmos-emulator-again branch from 2a78e83 to bde1f0d Compare May 24, 2026 22:56
Comment thread src/Cosmos/Cosmos.fs Outdated
$"""SELECT VALUE COUNT(1)
FROM item
WHERE item.id = @Id
AND (NOT IS_DEFINED(item.{deletedFieldName}) OR IS_NULL(item.{deletedFieldName}))"""

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@copilot так что с покрытием всех этих кейсов тестами?

Comment thread src/Cosmos/Cosmos.fs Outdated
Comment on lines +218 to +225
(deletedFieldName : string | null)
(id : string, [<Optional>] requiestOptions : QueryRequestOptions, [<Optional>] cancellationToken : CancellationToken)
=
task {
let deletedFieldName =
match deletedFieldName with
| null -> nullArg (nameof deletedFieldName)
| deletedFieldName -> deletedFieldName

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@copilot ты понимаешь что это идиотизм декларировать string | null а потом кидать исключение.

Suggested change
(deletedFieldName : string | null)
(id : string, [<Optional>] requiestOptions : QueryRequestOptions, [<Optional>] cancellationToken : CancellationToken)
=
task {
let deletedFieldName =
match deletedFieldName with
| null -> nullArg (nameof deletedFieldName)
| deletedFieldName -> deletedFieldName
(deletedFieldName : string)
(id : string, [<Optional>] requiestOptions : QueryRequestOptions, [<Optional>] cancellationToken : CancellationToken)
=
if deletedFieldName |> withNull |> isNull then
nullArg (nameof deletedFieldName)
task {

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Исправил в 69776da (уточнение в 1a73340): сигнатура теперь deletedFieldName : string, при этом runtime guard оставлен через nullArg для null-входа.

Comment thread src/Cosmos/Cosmos.fs
Copilot AI requested a review from xperiandri May 24, 2026 23:15

@xperiandri xperiandri left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@copilot изучи все методы на классе Assert и переделай все assert'ы на подходящие overloads.
Обработай все комментарии

Comment thread src/Cosmos/Cosmos.fs Outdated
$"""SELECT VALUE COUNT(1)
FROM item
WHERE item.id = @Id
AND (NOT IS_DEFINED(item.{deletedFieldName}) OR IS_NULL(item.{deletedFieldName}))"""

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

But it must be true to be treated as deleted
if it is { "deleted": false } it is not deleted

Comment thread src/Cosmos/Cosmos.fs Outdated
Comment on lines +245 to +258
let isAsciiLetter c = ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')
let isAsciiDigit c = '0' <= c && c <= '9'

let isValidDeletedFieldName =
if String.IsNullOrWhiteSpace deletedFieldName then
false
else
let firstCharacter = deletedFieldName[0]
let hasValidStart = firstCharacter = '_' || isAsciiLetter firstCharacter
let hasValidBody =
deletedFieldName
|> Seq.forall (fun c -> c = '_' || isAsciiLetter c || isAsciiDigit c)

hasValidStart && hasValidBody

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Это же правила валидации имени поля в Cosmos? Давай тогда создадим вверху файла модуль CosmosName и в нём функцию [<CompiledName "ValidateField">] validateField которая будет создержать этот код. И на эту функцию напишем тесты

Comment thread tests/Cosmos.Tests/BuilderUnitTests.fs Outdated
)

[<TestMethod>]
member _.``Read builder configures id partition key and request options`` () =

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
member _.``Read builder configures id partition key and request options`` () =
member _.``Read builder configures id and partition key and request options`` () =

Comment thread tests/Cosmos.Tests/BuilderUnitTests.fs Outdated
sessionToken "read-session"
}

Assert.IsTrue (operation.Id = "read-id", "Read builder should set id.")

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

там есть метод аля Assert.Equals для сравнения строк

Comment thread tests/Cosmos.Tests/BuilderUnitTests.fs Outdated
}

Assert.IsTrue (operation.Id = "read-id", "Read builder should set id.")
Assert.IsFalse (isNull operation.RequestOptions, "Read builder should initialize request options when needed.")

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

разве там нет метода Assert.IsNull?

Comment thread tests/Cosmos.Tests/BuilderUnitTests.fs Outdated

Assert.IsTrue (operation.Id = "read-id", "Read builder should set id.")
Assert.IsFalse (isNull operation.RequestOptions, "Read builder should initialize request options when needed.")
Assert.IsTrue (operation.RequestOptions.IfNoneMatchEtag = "etag-value", "Read builder should set eTag option.")

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Assert.Equals

Comment thread tests/Cosmos.Tests/BuilderUnitTests.fs Outdated
Assert.IsTrue (operation.Id = "read-id", "Read builder should set id.")
Assert.IsFalse (isNull operation.RequestOptions, "Read builder should initialize request options when needed.")
Assert.IsTrue (operation.RequestOptions.IfNoneMatchEtag = "etag-value", "Read builder should set eTag option.")
Assert.IsTrue (operation.RequestOptions.SessionToken = "read-session", "Read builder should set session token.")

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Assert.Equals

Comment thread tests/Cosmos.Tests/BuilderUnitTests.fs Outdated

let updateResult =
replaceConcurrentlyOperation.Update { id = "id"; partitionKey = "pk"; value = 2 }
|> Async.RunSynchronously

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

переделай на асинхронный тест

Agent-Logs-Url: https://github.com/fsprojects/FSharp.Azure.Cosmos/sessions/f0174b7d-c2d6-4a25-aa23-d50cac7c65f3

Co-authored-by: xperiandri <2365592+xperiandri@users.noreply.github.com>
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.

Integration tests against Cosmos Emulator

3 participants