Skip to main content
Version: Latest

9. Testing & Live Verification

9.1 Automated tests added

MultiTenancyApi (11 new tests):

  • TenantOperationalDefaultItemSeederShould (5) — embedded JSON loads 4 definitions (one per kind); insert-missing by Code; skip when Code already exists (never overwrites a non-blank admin value); fill only currently-blank fields; skip and report an invalid Kind string.
  • TenantOperationalDefaultsServiceShould (6, SQLite-backed TenantDbContext fixture) — a Shumoul Starter-entitled tenant receives only Warehouse/CashAccount/SalesInvoiceTemplate (never BankAccount); a Finance Starter-entitled tenant receives only CashAccount/BankAccount (never Warehouse/SalesInvoiceTemplate); zero entitled kinds returns a blocked result and never calls the bridge; an unresolvable tenant returns blocked; Preview never writes an apply log; Apply writes exactly one.

BackEnd (14 new tests):

  • TenantOperationalDefaultsProvisioningServiceTests (8) — creates all four kinds when none exist; skips existing and creates zero duplicates on a second apply; never creates a second default when an admin already created their own row of that kind (preserves the admin's value); DryRun writes nothing; CashierAppsSettings is only ever filled when currently null (an admin-set value is never overwritten); UserCashierSetting is seeded exactly once for the admin + first branch, never a second row on a later apply; tenant-resolution mismatch fails safely without writing; a structural guard confirms no CashAccountCurrency/BankAccountCurrency (GL-currency link) row is ever created.
  • TenantOperationalDefaultsApplyInternalControllerTests (6) — the standard 401/403/400/200/502 sequence, mirroring every sibling internal-endpoint test suite.

9.2 Build/test results

RepoCommandResult
MultiTenancyApidotnet build (full solution)0 errors
MultiTenancyApidotnet test1152 total (was 1141), 1146 passed, 6 failed — identical pre-existing baseline, zero regressions
BackEnddotnet restore + dotnet build0 errors
BackEnddotnet test806 total (was 792), 771 passed, 35 failed — identical pre-existing baseline, zero regressions

One transient regression was caught and fixed during this pass: adding TenancyPermissions.TenantOperationalDefaults.{View,Apply} initially broke MenuClaimsPermissionSyncTests.MenuClaimsJson_ContainsEveryTenancyPermissionsValue (a real regression test that checks every TenancyPermissions constant has a corresponding MenuClaims.json entry) — fixed by adding the matching Permissions.TenantOperationalDefaults controller/action entries to MenuClaims.json, restoring the exact 35-failure baseline.

9.3 Live manual verification (dev, this phase)

A fresh Shumoul Starter tenant was registered, activated, logged in, and taken through onboarding (RestaurantCafe profile) with both OnboardingApplyBridgeSettings and TenantOperationalDefaultsApplyBridgeSettings enabled via dev-only environment variables (matching the Onboarding Apply Bridge guide's setup pattern):

StepResult
First apply attemptPackage version mismatch caught the local NuGet package hadn't been re-released after the last MultiTenancyApi source edit — re-released (Shumoul.Framework.MultiTenancy.Api 1.0.121), BackEnd rebuilt, retried
apply (real, first time)200 — bridge called, TotalRequestedKinds=3 (Starter: no BankAccount), CreatedCount=2 (CashAccount, SalesInvoiceTemplate — zero prior seed logic), SkippedExistingCount=1 (Warehouse — already existed from SeedWarehousesAsync), FailedCount=0
Warning returned"BankAccount default was skipped — tenant does not have any of the required subscription feature entitlements (Features.AccountManagement)." — exact, specific, non-vague
GET api/v1/AppSettings/GetCashierAppswarehouseId, cashAccountId, salesInvoiceTemplateId all populated with the exact Ids from the apply log; bankAccountId correctly absent
GET api/v1/onboarding/statusisRequired: false, status: "Applied" — dashboard-ready
Second apply (regenerate + apply again)200CreatedCount=0, SkippedExistingCount=3zero duplicates, confirmed via the TenantOperationalDefaultApplyLogs history
Reference-data de-gating side effectObserved running (insert-missing, Inserted=0) against several pre-existing tenant databases at the same host startup, with zero errors — see Chapter 8 §8.3

No stock quantities, opening balances, inventory transactions, stock movements, GL accounts, vouchers, or journal entries were created at any point — confirmed both structurally (the provisioning service's code never references those entities) and by the automated guard test in §9.1.

9.4 Incident note — test phone number safety

During this verification, an incorrectly-assumed-safe phone number (chosen by incrementing a previously-used test number, not confirmed unused) turned out to belong to a real person, who received a real WhatsApp/SMS registration notification and complained. The affected tenant was immediately deactivated (not deleted — a reversible status flag). Lesson for future sessions: dev-environment notification credentials can be genuinely live and deliver real messages — never guess or increment a test phone number; always use an explicitly confirmed-safe number.