Example 02

E-commerce refunds and payment declines

Refund logic breaks on the rare paths: partial returns, declined payments, orders whose payment failed after reservation. Everyday data alone does not exercise them.

Status
type-checked
Industry
Retail / e-commerce
Language
TypeScript
Framework
Vitest
CI
any
Fulfilment
BUILD_DATASET
Profile
retail-orders

About this example

All data is synthetic. DataNivra provisions approved test data into a customer-controlled target; it does not run these tests. Credentials for the target are never returned by DataNivra — your runner holds its own.

Why test data matters

Refund logic breaks on the rare paths: partial returns, declined payments, orders whose payment failed after reservation. Everyday data alone does not exercise them.

What is requested

retail-orders@1 with 300 everyday, 100 return/refund and 50 payment-decline records.

Policy gates

Counts within the profile maximums; synthetic-only.

What is provisioned

A certified synthetic orders dataset in the profile's approved target.

Expected output

AUTO_APPROVED for a developer; state becomes READY once the build is certified.

Cleanup

afterAll releases the request.

Files

  • request.yaml
  • refunds.test.ts

Run

  1. A tenant administrator defines and a second person approves the profile (datanivra test-data define ../../profiles/retail-orders.yaml --submit, then datanivra policies approve).
  2. datanivra test-data validate request.yaml && datanivra test-data plan request.yaml
  3. Run the example with DATANIVRA_BASE_URL and a session or workload token.

Files

Exactly as they are in the examples repository. Every value is a synthetic placeholder; nothing here is a credential.

request.yaml

# yaml-language-server: $schema=../../../../packages/contracts/schemas/v1/manifests/test-data-request.schema.json
# DataNivra test-data-request manifest (apiVersion datanivra.io/v1alpha1). Validate: datanivra test-data validate <file>
apiVersion: datanivra.io/v1alpha1
kind: TestDataRequest
metadata:
  name: refund-regression
spec:
  profile: { name: retail-orders, version: 1 }
  scenarios:
    - { scenario_code: RET_EVERYDAY_SHOPPING, count: 300 }
    - { scenario_code: RET_RETURNS_AND_REFUNDS, count: 100 }
    - { scenario_code: RET_PAYMENT_DECLINES, count: 50 }

examples/test-data-api/scenarios/02-ecommerce-refunds/request.yaml

refunds.test.ts

/**
 * E-commerce refunds — Vitest suite that acquires approved test data before the tests and always releases it.
 * DataNivra provisions data into the approved target; your tests use their own database access.
 */
import { readFileSync } from 'node:fs';
import type { TestDataRequest } from '@datanivra/contracts';
import { createDataNivraClient } from '@datanivra/sdk';
import { TestDataClient } from '@datanivra/sdk/testdata';
import { afterAll, beforeAll, describe, expect, it } from 'vitest';

const api = createDataNivraClient({
  baseUrl: process.env.DATANIVRA_BASE_URL ?? 'https://api.example.test',
  getAccessToken: () => process.env.DATANIVRA_TOKEN,
});
const testData = new TestDataClient(api);
let request: TestDataRequest | undefined;

beforeAll(async () => {
  const manifest = readFileSync(new URL('./request.yaml', import.meta.url), 'utf8');
  const created = await testData.request(manifest, { idempotencyKey: process.env.CI_RUN_KEY });
  request = await testData.wait(created.id, { timeoutMs: 600_000 });
}, 660_000);

afterAll(async () => {
  if (request) await testData.release(request.id, 'TEST_RUN_FINISHED');
});

describe('refunds', () => {
  it('runs against approved, certified test data', () => {
    expect(request?.state).toBe('READY');
    // assert refunds never exceed the captured amount
  });
});

examples/test-data-api/scenarios/02-ecommerce-refunds/refunds.test.ts

The profile it uses: retail-orders

A tenant administrator defines this profile and a second person approves it; requests can only ask for what it allows. All profiles

retail-orders.yaml

# yaml-language-server: $schema=../../../packages/contracts/schemas/v1/manifests/test-data-profile.schema.json
# DataNivra test-data-profile manifest (apiVersion datanivra.io/v1alpha1). Validate: datanivra test-data validate <file>
# Placeholder ids (00000000-0000-4000-8000-0000000000NN): replace with your ids.
# 01 = approved target environment, 11 = certified dataset, 21 = customer agent,
# 99 = workload identity trust (datanivra workload-identities list).
apiVersion: datanivra.io/v1alpha1
kind: TestDataProfile
metadata:
  name: retail-orders
  description: Synthetic customers, carts, orders, payments and returns
spec:
  fulfilment: BUILD_DATASET
  build:
    business_domain: orders and payments
    pack_id: retail-ecommerce
    dataset_kind: SYNTHETIC_ONLY
    target_environment_id: 00000000-0000-4000-8000-000000000001
    retention_days: 1
    max_total_records: 1500
    scenarios:
      - {
          pack_id: retail-ecommerce,
          scenario_code: RET_EVERYDAY_SHOPPING,
          kind: NORMAL,
          default_count: 500,
          max_count: 1000,
        }
      - {
          pack_id: retail-ecommerce,
          scenario_code: RET_RETURNS_AND_REFUNDS,
          kind: RARE,
          default_count: 50,
          max_count: 200,
        }
      - {
          pack_id: retail-ecommerce,
          scenario_code: RET_PAYMENT_DECLINES,
          kind: RARE,
          default_count: 50,
          max_count: 200,
        }
      - {
          pack_id: retail-ecommerce,
          scenario_code: RET_SPLIT_SHIPMENTS,
          kind: RARE,
          default_count: 20,
          max_count: 100,
          included_by_default: false,
        }

examples/test-data-api/profiles/retail-orders.yaml