---
id: TST-COM-CAT-096
title: Promotions Verification
kind: api-lifecycle
product_area: commerce
module: catalog
revision: 1
status: draft
product_intent: proposed
source_sha:
  services-commerce: c8b66a98e2490617aec38ba5c8165dd9bd0a8f9b
repository: services-commerce
files:
  - modules/promotions/tests/e2e/promotions.e2e.spec.js
implements:
  - ATS-COM-CAT-014-01
  - ATS-COM-CAT-014-03
  - ATS-COM-CAT-014-04
  - ATS-COM-CAT-014-05
  - ATS-COM-CAT-014-06
  - ATS-COM-CAT-014-07
  - ATS-COM-CAT-014-08
  - ATS-COM-CAT-015-02
environment: local
implementation_state: implemented
latest_result: not-run
latest_run_at: null
latest_run_ref: null
conformance: not-verified
estimated_minutes: 2
isolation: 'Suite-owned workspace keys and database fixtures, removed by its cleanup hooks.'
binding_evidence:
  - scenario: ATS-COM-CAT-014-01
    source: >-
      services-commerce:modules/promotions/tests/e2e/promotions.e2e.spec.js#refuses to make a draft
      with a code automatic, 409 automatic_promotion_has_no_codes
  - scenario: ATS-COM-CAT-014-01
    source: >-
      services-commerce:modules/promotions/tests/e2e/promotions.e2e.spec.js#makes a draft with no
      code automatic, and refuses the change once it is active, 409 kind_not_editable
  - scenario: ATS-COM-CAT-014-01
    source: >-
      services-commerce:modules/promotions/tests/e2e/promotions.e2e.spec.js#refuses a code, 409
      automatic_promotion_has_no_codes
  - scenario: ATS-COM-CAT-014-03
    source: >-
      services-commerce:modules/promotions/tests/e2e/promotions.e2e.spec.js#refuses an area nobody
      offers, 400 promotion_invalid naming the part
  - scenario: ATS-COM-CAT-014-03
    source: >-
      services-commerce:modules/promotions/tests/e2e/promotions.e2e.spec.js#refuses a product that
      is not merchandise, 400 promotion_invalid naming the part and the product
  - scenario: ATS-COM-CAT-014-04
    source: >-
      services-commerce:modules/promotions/tests/e2e/promotions.e2e.spec.js#names every problem of a
      sloppy promotion in one 400 promotion_invalid, the zero cap among them (Q07, journey 0203)
  - scenario: ATS-COM-CAT-014-05
    source: >-
      services-commerce:modules/promotions/tests/e2e/promotions.e2e.spec.js#refuses a
      promotion-level eligibility rule on a code-claimed promotion, 400 in the code’s words
  - scenario: ATS-COM-CAT-014-05
    source: >-
      services-commerce:modules/promotions/tests/e2e/promotions.e2e.spec.js#accepts a scope of any
      members and ignores it: never an error, nothing stored (Revision 2)
  - scenario: ATS-COM-CAT-014-06
    source: >-
      services-commerce:modules/promotions/tests/e2e/promotions.e2e.spec.js#defaults "combine with
      audience prices" to yes when the body leaves it out (D12)
  - scenario: ATS-COM-CAT-014-06
    source: >-
      services-commerce:modules/promotions/tests/e2e/promotions.e2e.spec.js#changes "combine with
      audience prices" and reads it back (D12)
  - scenario: ATS-COM-CAT-014-07
    source: >-
      services-commerce:modules/promotions/tests/e2e/promotions.e2e.spec.js#pauses an active
      promotion, resumes a paused one, and activates a paused one
  - scenario: ATS-COM-CAT-014-07
    source: >-
      services-commerce:modules/promotions/tests/e2e/promotions.e2e.spec.js#ends an active
      promotion, and archives an ended one and a draft
  - scenario: ATS-COM-CAT-014-07
    source: >-
      services-commerce:modules/promotions/tests/e2e/promotions.e2e.spec.js#names both states in the
      refusal
  - scenario: ATS-COM-CAT-014-07
    source: >-
      services-commerce:modules/promotions/tests/e2e/promotions.e2e.spec.js#records every transition
      on the history, newest first, with the reason given
  - scenario: ATS-COM-CAT-014-08
    source: >-
      services-commerce:modules/promotions/tests/e2e/promotions.e2e.spec.js#refuses to activate a
      coded promotion with no active code, 409 no_active_code
  - scenario: ATS-COM-CAT-014-08
    source: >-
      services-commerce:modules/promotions/tests/e2e/promotions.e2e.spec.js#refuses to activate a
      promotion whose parts were removed, 409 offer_required
  - scenario: ATS-COM-CAT-014-08
    source: >-
      services-commerce:modules/promotions/tests/e2e/promotions.e2e.spec.js#refuses activating an
      effect with no rule chosen yet, 409 eligibility_rule_required
  - scenario: ATS-COM-CAT-015-02
    source: >-
      services-commerce:modules/promotions/tests/e2e/promotions.e2e.spec.js#refuses a code, 409
      automatic_promotion_has_no_codes
evidence:
  - 'services-commerce:modules/promotions/tests/e2e/promotions.e2e.spec.js'
  - >-
    services-commerce:modules/promotions/tests/e2e/promotions.e2e.spec.js#Real: the composed
    handler, the routes, the mapper, the workflows, the persistence and PostgreSQL.
  - >-
    services-commerce:modules/promotions/tests/e2e/promotions.e2e.spec.js#Doubled: the signing key
    pair. Every call acts in a tenant of the spec's own, registered in the local `platform.tenants`
    stand-in and removed in `after`; the list's cases act in a second tenant of their own, so its
    rows are exactly the ones they make.
execution_constraints:
  - No execution is performed in this documentation back-fill.
verification_boundary: >-
  Bindings identify the existing assertions contributing to each scenario; several suites can
  jointly cover a compound scenario.
---

# Promotions Verification

## Verification Boundary

The composed API handler runs locally with signed caller contexts and the integration database. Its route, mapping, permission and persistence assertions establish the local API boundary.

## What This Suite Proves

The promotions assertions contribute to the scenarios listed in the register. Each binding retains its exact source test anchor so a reviewer can distinguish an individual contribution from the complete scenario.

## What It Does Not Prove

The register records source inspection only. It establishes no run result, delivery qualification or Product approval.

## Real Dependencies and Test Doubles

PostgreSQL and the services called by the suite are real. External service ports, file storage and queues may use the fixtures declared by the suite and its support helpers.

## Must Not Be Doubled

Keep the asserted database constraints, transactions, service functions and execution contexts real. For API suites, preserve the dispatcher and permission enforcement.
