Skip to content

fix: business unit key uniqueness and auth clear on ctMock.clear() - #432

Merged
robertmoelker merged 5 commits into
labd:mainfrom
robertmoelker:fix/business-unit-key-uniqueness-and-auth-clear
Sep 15, 2026
Merged

robertmoelker merged 5 commits into
labd:mainfrom
robertmoelker:fix/business-unit-key-uniqueness-and-auth-clear

Conversation

@robertmoelker

@robertmoelker robertmoelker commented Sep 11, 2026 •

Copy link
Copy Markdown
Contributor

Enforce business unit key uniqueness on create

The key of a BusinessUnit is unique within a project, but the mock accepted duplicates and stored both — getByKey
then resolved to whichever was created first. Creating a business unit with a key that is already taken now returns a
400 DuplicateField error on the key field, as commercetools does. There is no setKey/changeKey update action
for business units, so create is the only path that needs the check.

Reset the auth store on clear()

clear() only emptied the resource storage, so every token ever issued stayed in the OAuth2Store. A token outlived
the customer or anonymous session it was issued for, kept passing validation, and leaked identity into the next test.
OAuth2Store.clear() now drops the issued tokens and their client mapping, and ctMock.clear() calls it.

robertmoelker and others added 3 commits September 11, 2026 10:41
The key of a BusinessUnit is unique within a project, but the mock
accepted duplicates and stored both, so getByKey would resolve to
whichever came first. Creating a duplicate now fails with a 400
DuplicateField error on the key field, as it does on commercetools.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
clear() only emptied the resource storage, so every token ever issued
stayed in the OAuth2Store. A token outlived the customer or anonymous
session it was issued for, kept passing validation, and leaked identity
into the next test.

OAuth2Store.clear() drops the issued tokens and their client mapping,
and ctMock.clear() calls it. The /me tests now issue their session per
test, since the token no longer survives the clear() in afterEach.
@changeset-bot

changeset-bot Bot commented Sep 11, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: f178dcb

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@labdigital/commercetools-mock Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@robertmoelker
robertmoelker merged commit 756eb56 into labd:main Sep 15, 2026
10 checks passed
robertmoelker pushed a commit that referenced this pull request Sep 15, 2026
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and the packages will
be published to npm automatically. If you're not ready to do a release
yet, that's fine, whenever you add more changesets to main, this PR will
be updated.

⚠️⚠️⚠️⚠️⚠️⚠️

`main` is currently in **pre mode** so this branch has prereleases
rather than normal releases. If you want to exit prereleases, run
`changeset pre exit` on `main`.

⚠️⚠️⚠️⚠️⚠️⚠️

# Releases
## @labdigital/commercetools-mock@5.0.0-beta.1

### Minor Changes

- [#435](#435)
[`7a33c6b`](7a33c6b)
Thanks [@robertmoelker](https://github.com/robertmoelker)! - Support
custom fields on addresses. `BaseAddress` is polymorphic between read
and write, so address drafts can carry a `custom` field holding a
`CustomFieldsDraft`. Drafts and update actions carrying such an address
(customer, business unit, cart, order and channel) now resolve it to
`CustomFields` against the referenced type, returning a 400
`ReferencedResourceNotFound` when the type does not exist. In strict
mode the generated draft schemas accept and validate `custom` on an
address.
  
Customer and business unit creation, and the `addAddress` customer
action, now go through the shared `createAddress` helper, which means
the address `country` field is enforced there as well.

- [#430](#430)
[`2e8ae39`](2e8ae39)
Thanks [@mvantellingen](https://github.com/mvantellingen)! - Persist
`expansionPaths`, `dependencies` and `additionalContext` when creating
  an API Extension.
  
The Extension repository only copied `key`, `timeoutInMs`, `destination`
and
`triggers` out of the draft, so the three fields added by the 2026-03-12
API
release were silently dropped on create. `POST /{projectKey}/extensions`
with
`expansionPaths` returned an extension without them, which made it look
like
  the field was rejected. The `setExpansionPaths`, `setDependencies` and
`setAdditionalContext` update actions were already implemented, so only
the
  create path was affected.
  
`dependencies` are now resolved through the storage layer like every
other
resource identifier, so they can be given by `key` as well as by `id`
(on both
create and `setDependencies`, which previously assumed `id` was set) and
an
unknown dependency returns a `ReferencedResourceNotFound` error instead
of a
  reference with `id: undefined`.

### Patch Changes

- [#433](#433)
[`74adf7c`](74adf7c)
Thanks [@robertmoelker](https://github.com/robertmoelker)! - Update
astro (docs) to v7.* for security reasons

- [#432](#432)
[`756eb56`](756eb56)
Thanks [@robertmoelker](https://github.com/robertmoelker)! - Enforce
BusinessUnit key uniqueness within a project. Creating a business unit
with a key that is already taken now returns a 400 `DuplicateField`
error on the `key` field instead of silently storing a second unit under
the same key.

- [#432](#432)
[`756eb56`](756eb56)
Thanks [@robertmoelker](https://github.com/robertmoelker)! - `clear()`
now also resets the auth store. Tokens issued before a `clear()` used to
stay valid and keep resolving to customers and anonymous sessions that
no longer existed, leaking identity between tests. Tests that issue a
token (for example through `customerSession`) must do so after each
`clear()`.

- [#434](#434)
[`cb56f14`](cb56f14)
Thanks [@robertmoelker](https://github.com/robertmoelker)! - Scope
customer email uniqueness to the stores a customer is assigned to. The
same email can now be used in different stores, matching commercetools
behaviour. Customers created through an in-store endpoint are assigned
to that store, and the in-store password flow only matches customers of
that store.
  
Implement the `addStore`, `removeStore` and `setStores` customer update
actions, which re-validate email uniqueness for any store scope the
customer newly enters (including becoming a global customer again).
  
Store resource identifiers are now validated by `key` as well as by
`id`, so referencing a non-existent store in a draft returns a 400
`ReferencedResourceNotFound` error instead of silently passing through.
This also fixes `getStoreKeyReference`, which previously always failed
for `id`-based references.
  
In-store endpoints (`/{projectKey}/in-store/key={storeKey}/...`) now
return a 404 `ResourceNotFound` when the store in the path does not
exist, matching commercetools.

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@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.

2 participants