description: "CRUD Api Version 1 (strict)"

schemaVersion: "1.4"

runOnRequirements:
  - minServerVersion: "4.9"

createEntities:
  - client:
      id: &client client
      observeEvents:
        - commandStartedEvent
      serverApi:
        version: "1"
        strict: true
  - database:
      id: &database database
      client: *client
      databaseName: &databaseName versioned-api-tests
  - database:
      id: &adminDatabase adminDatabase
      client: *client
      databaseName: &adminDatabaseName admin
  - collection:
      id: &collection collection
      database: *database
      collectionName: &collectionName test

_yamlAnchors:
  versions:
    - &expectedApiVersion
      apiVersion: "1"
      apiStrict: true
      apiDeprecationErrors: { $$unsetOrMatches: false }

initialData:
  - collectionName: *collectionName
    databaseName: *databaseName
    documents:
      - { _id: 1, x: 11 }
      - { _id: 2, x: 22 }
      - { _id: 3, x: 33 }
      - { _id: 4, x: 44 }
      - { _id: 5, x: 55 }

tests:
  - description: "aggregate on collection appends declared API version"
    operations:
      - name: aggregate
        object: *collection
        arguments:
          pipeline: &pipeline
            - $sort: { x : 1 }
            - $match: { _id: { $gt: 1 } }
    expectEvents:
      - client: *client
        events:
          - commandStartedEvent:
              command:
                aggregate: *collectionName
                pipeline: *pipeline
                <<: *expectedApiVersion

  - description: "aggregate on database appends declared API version"
    runOnRequirements:
        # serverless does not support either of the current database-level aggregation stages ($listLocalSessions and
        # $currentOp)
      - serverless: "forbid"
    operations:
      - name: aggregate
        object: *adminDatabase
        arguments:
          pipeline: &pipeline
            - $listLocalSessions: {}
            - $limit: 1
        expectError:
          errorCodeName: "APIStrictError"
    expectEvents:
      - client: *client
        events:
          - commandStartedEvent:
              command:
                aggregate: 1
                pipeline: *pipeline
                <<: *expectedApiVersion

  - description: "bulkWrite appends declared API version"
    operations:
      - name: bulkWrite
        object: *collection
        arguments:
          requests:
            - insertOne:
                document: { _id: 6, x: 66 }
            - updateOne:
                filter: { _id: 2 }
                update: { $inc: { x: 1 } }
            - deleteMany:
                filter: { x: { $nin: [ 24, 34 ] } }
            - updateMany:
                filter: { _id: { $gt: 1 } }
                update: { $inc: { x: 1 } }
            - deleteOne:
                filter: { _id: 7 }
            - replaceOne:
                filter: { _id: 4 }
                replacement: { _id: 4, x: 44 }
                upsert: true
          ordered: true
    expectEvents:
      - client: *client
        events:
          - commandStartedEvent:
              command:
                insert: *collectionName
                documents:
                  - { _id: 6, x: 66 }
                <<: *expectedApiVersion
          - commandStartedEvent:
              command:
                update: *collectionName
                updates:
                  - q: { _id: 2 }
                    u: { $inc: { x: 1 } }
                    multi: { $$unsetOrMatches: false }
                    upsert: { $$unsetOrMatches: false }
                <<: *expectedApiVersion
          - commandStartedEvent:
              command:
                delete: *collectionName
                deletes:
                  - { q: { x: { $nin: [ 24, 34 ] } }, limit: 0 }
                <<: *expectedApiVersion
          - commandStartedEvent:
              command:
                update: *collectionName
                updates:
                  - q: { _id: { $gt: 1 } }
                    u: { $inc: { x: 1 } }
                    multi: true
                    upsert: { $$unsetOrMatches: false }
                <<: *expectedApiVersion
          - commandStartedEvent:
              command:
                delete: *collectionName
                deletes:
                  - { q: { _id: 7 }, limit: 1 }
                <<: *expectedApiVersion
          - commandStartedEvent:
              command:
                update: *collectionName
                updates:
                  - q: { _id: 4 }
                    u: { _id: 4, x: 44 }
                    multi: { $$unsetOrMatches: false }
                    upsert: true
                <<: *expectedApiVersion

  - description: "countDocuments appends declared API version"
    operations:
      - name: countDocuments
        object: *collection
        arguments:
          filter: &filter
            x : { $gt: 11 }
    expectEvents:
      - client: *client
        events:
          - commandStartedEvent:
              command:
                aggregate: *collectionName
                pipeline:
                  - { $match: *filter }
                  - { $group: { _id: 1, n: { $sum: 1 } } }
                <<: *expectedApiVersion

  - description: "deleteMany appends declared API version"
    operations:
      - name: deleteMany
        object: *collection
        arguments:
          filter: { x: { $nin: [ 24, 34 ] } }
    expectEvents:
      - client: *client
        events:
          - commandStartedEvent:
              command:
                delete: *collectionName
                deletes:
                  - { q: { x: { $nin: [ 24, 34 ] } }, limit: 0 }
                <<: *expectedApiVersion

  - description: "deleteOne appends declared API version"
    operations:
      - name: deleteOne
        object: *collection
        arguments:
          filter: { _id: 7 }
    expectEvents:
      - client: *client
        events:
          - commandStartedEvent:
              command:
                delete: *collectionName
                deletes:
                  - { q: { _id: 7 }, limit: 1 }
                <<: *expectedApiVersion

  # distinct will fail until drivers replace it with an alternative
  # implementation
  - description: "distinct appends declared API version"
    operations:
      - name: distinct
        object: *collection
        arguments:
          fieldName: x
          filter: {}
        expectError:
          isError: true
          errorContains: "command distinct is not in API Version 1"
          errorCodeName: "APIStrictError"
    expectEvents:
      - client: *client
        events:
          - commandStartedEvent:
              command:
                distinct: *collectionName
                key: x
                <<: *expectedApiVersion

  - description: "estimatedDocumentCount appends declared API version"
    # See: https://jira.mongodb.org/browse/SERVER-63850
    runOnRequirements:
      - minServerVersion: "5.0.9"
        maxServerVersion: "5.0.99"
      - minServerVersion: "5.3.2"
    operations:
      - name: estimatedDocumentCount
        object: *collection
        arguments: {}
    expectEvents:
      - client: *client
        events:
          - commandStartedEvent:
              command:
                count: *collectionName
                <<: *expectedApiVersion

  - description: "find and getMore append API version"
    operations:
      - name: find
        object: *collection
        arguments:
          filter: {}
          sort: { _id: 1 }
          batchSize: 3
        expectResult:
          - { _id: 1, x: 11 }
          - { _id: 2, x: 22 }
          - { _id: 3, x: 33 }
          - { _id: 4, x: 44 }
          - { _id: 5, x: 55 }
    expectEvents:
      - client: *client
        events:
          - commandStartedEvent:
              command:
                find: *collectionName
                <<: *expectedApiVersion
          - commandStartedEvent:
              command:
                getMore: { $$type: [ int, long ] }
                <<: *expectedApiVersion

  - description: "findOneAndDelete appends declared API version"
    operations:
      - name: findOneAndDelete
        object: *collection
        arguments:
          filter: &filter { _id: 1 }
    expectEvents:
      - client: *client
        events:
          - commandStartedEvent:
              command:
                findAndModify: *collectionName
                query: *filter
                remove: true
                <<: *expectedApiVersion

  - description: "findOneAndReplace appends declared API version"
    operations:
      - name: findOneAndReplace
        object: *collection
        arguments:
          filter: &filter { _id: 1 }
          replacement: &replacement { x: 33 }
    expectEvents:
      - client: *client
        events:
          - commandStartedEvent:
              command:
                findAndModify: *collectionName
                query: *filter
                update: *replacement
                <<: *expectedApiVersion

  - description: "findOneAndUpdate appends declared API version"
    operations:
      - name: findOneAndUpdate
        object: collection
        arguments:
          filter: &filter { _id: 1 }
          update: &update { $inc: { x: 1 } }
    expectEvents:
      - client: *client
        events:
          - commandStartedEvent:
              command:
                findAndModify: *collectionName
                query: *filter
                update: *update
                <<: *expectedApiVersion

  - description: "insertMany appends declared API version"
    operations:
      - name: insertMany
        object: *collection
        arguments:
          documents:
            - { _id: 6, x: 66 }
            - { _id: 7, x: 77 }
    expectEvents:
      - client: *client
        events:
          - commandStartedEvent:
              command:
                insert: *collectionName
                documents:
                  - { _id: 6, x: 66 }
                  - { _id: 7, x: 77 }
                <<: *expectedApiVersion

  - description: "insertOne appends declared API version"
    operations:
      - name: insertOne
        object: *collection
        arguments:
          document: { _id: 6, x: 66 }
    expectEvents:
      - client: *client
        events:
          - commandStartedEvent:
              command:
                insert: *collectionName
                documents:
                  - { _id: 6, x: 66 }
                <<: *expectedApiVersion

  - description: "replaceOne appends declared API version"
    operations:
      - name: replaceOne
        object: *collection
        arguments:
          filter: { _id: 4 }
          replacement: { _id: 4, x: 44 }
          upsert: true
    expectEvents:
      - client: *client
        events:
          - commandStartedEvent:
              command:
                update: *collectionName
                updates:
                  - q: { _id: 4 }
                    u: { _id: 4, x: 44 }
                    multi: { $$unsetOrMatches: false }
                    upsert: true
                <<: *expectedApiVersion

  - description: "updateMany appends declared API version"
    operations:
      - name: updateMany
        object: *collection
        arguments:
          filter: { _id: { $gt: 1 } }
          update: { $inc: { x: 1 } }
    expectEvents:
      - client: *client
        events:
          - commandStartedEvent:
              command:
                update: *collectionName
                updates:
                  - q: { _id: { $gt: 1 } }
                    u: { $inc: { x: 1 } }
                    multi: true
                    upsert: { $$unsetOrMatches: false }
                <<: *expectedApiVersion

  - description: "updateOne appends declared API version"
    operations:
      - name: updateOne
        object: *collection
        arguments:
          filter: { _id: 2 }
          update: { $inc: { x: 1 } }
    expectEvents:
      - client: *client
        events:
          - commandStartedEvent:
              command:
                update: *collectionName
                updates:
                  - q: { _id: 2 }
                    u: { $inc: { x: 1 } }
                    multi: { $$unsetOrMatches: false }
                    upsert: { $$unsetOrMatches: false }
                <<: *expectedApiVersion
