Use a private test server and disposable shop/token data. Test with at least two ordinary players plus one staff account so permission boundaries and queue ordering are visible.
- Confirm WorldGuard contains region
shopsin worldgeneral, or change the twostorefront-discoverynames to the test fixtures. - Run
/shops reloadand wait for the public catalogue ready log line. - Run
/shops admin advertise currency status. It should say no template is captured on a clean setup. - Obtain one genuine token through the real
/afkshrinetrade, hold it in the main hand, and run/shops admin advertise currency capture. - Run
/shops admin advertise currency statusagain. Keep the setup token; capture should not consume it.
Create these normal test shops inside the marketplace region:
- an in-stock
STONE_BRICKScustomer-buy shop; - an out-of-stock
STONE_BRICKScustomer-buy shop; - a
STONE_BRICKSshop that only buys from customers; - at least five in-stock
STONE_BRICKSshops across two owners for pagination and owner interleaving; - one admin shop selling
STONE_BRICKS; - one normal shop just outside the marketplace region.
Use /shops list to record each shop's displayed #ID.
Look directly at one of your shops and run /shops inspect. Confirm its details
appear immediately, no selection prompt appears, and the unique #ID matches
/shops list. Look away and run it again; confirm ShopChest asks for a click and
then inspects the selected shop. A second ordinary player should not see the ID
for someone else's shop, while a staff account should see it.
For one normal customer-buy shop, exercise each stock-update path. Empty and
restock it with ordinary clicks, shift-clicks, an inventory drag, and a hopper,
then confirm the hologram updates immediately after the inventory settles. Also
change its contents with a command or test helper that bypasses inventory
events. Without opening or touching the container afterward, verify the stale
[Out of stock] state repairs itself within a few seconds. Repeat with a full
configured bundle of an enchanted book to confirm exact metadata matching.
As an ordinary shop owner, run:
/shops profile
/shops profile set name JahLion's Gear
/shops profile set advertisement Need protection? I sell OP armor and weapons
/shops profile set description Armor, weapons, and adventure gear
/shops profile set location At /warp shops, look for the lion head on the left
/shops profile
/shops profile shops 1
Verify the fields, shop counts, Customer-Buy stock, Customer-Sell capacity,
four-row page size, coordinates, and clickable /warp shops link. Hover the
item row, price line, and coordinates and confirm each names the same unique
shop ID. Confirm that the coordinates themselves do not teleport the ordinary
player. From the second account, verify /shops profile suggests only profile
actions and shopowner, while /shops profile shopowner suggests online
player names. View the same profile by player name and UUID through that route.
Create or locate an enchanted-book shop plus regular, splash, and lingering potion shops. In both profile shop pages and search results, hover each generic item name and verify Minecraft's item tooltip shows the exact stored enchantments or potion effects. In profile pages, verify the bullet, quantity, price, and coordinates still show the shop-ID tooltip. Confirm an ordinary item name in search results has no item tooltip.
Run each invalid text case and confirm it is rejected without changing the previous value:
/shops profile set description &aGreen shop
/shops profile set description <green>Green shop</green>
/shops profile set description https://example.com
/shops profile set description %player_name%
Also test an empty value, a line break pasted into chat, and text one character over each documented limit. Then clear and restore one field:
/shops profile clear description
/shops profile set description Armor, weapons, and adventure gear
Feature the recorded IDs in order:
/shops profile featured add <in-stock-shop-id>
/shops profile featured add <second-in-stock-shop-id>
/shops profile featured add <third-in-stock-shop-id>
/shops profile featured add <fourth-shop-id>
Before entering an ID manually, type /shops profile featured add and press
Tab. Suggestions must contain only this player's scoped, normal Customer-Buy
shop IDs. Trigger the grey add-command prompt from /shops advertise, click
it, and confirm it opens the owner's four-row shop page. Eligible rows must
show #ID plus a clickable Feature action; already featured rows must offer a
clickable Remove action; customer-sell-only rows must say they are ineligible.
The first three should succeed and retain order; the fourth should be rejected.
Confirm that another owner's ID, an admin-shop ID, and a customer-sell-only ID
are rejected. Exercise featured remove and featured clear, then restore at
least one in-stock primary listing.
As staff, test moderation:
/shops admin storefront JahLion hide
/shops admin storefront JahLion show
/shops admin storefront JahLion suspend
/shops admin storefront JahLion unsuspend
/shops admin storefront JahLion clear
hide should suppress player-written text but preserve eligible listings.
suspend should remove the storefront from profile, search, advertising, and
export. clear should remove text without deleting shop or Featured Listing
records and should retain the current moderation flags.
As an eligible owner, place an Ender Chest with air above it and run:
/shops profile display status
/shops profile display create
Right-click a wrong block and confirm selection remains active, then right-click
the Ender Chest. Verify the panel shows the profile name, owner, bounded profile
text, live shop/selling/buying counts, and the profile command. Confirm the
Ender Chest still opens as the player's ordinary personal Ender Chest, does not
trade on either click, shows the configured rotating landmark item rather than
a shop product, and does not change /shops limits. Confirm no live End Crystal
entity exists and the landmark therefore cannot explode, take damage, or drop.
Walk from outside the configured view distance toward the chest: the item
should appear only nearby, and the soft aqua, player-local dust-particle orbit
should begin at its smaller radius and become denser on approach. It
should be easy to distinguish from the Ender Chest's native purple particles.
Try to create a second display, use another player's occupied anchor, obstruct
the block above, place in a protected location, start another ShopChest
selection first, and let selection expire. Each path must fail without creating
a record. Rapidly repeat create and verify the owner and anchor uniqueness
constraints still leave only one display.
Unload and reload the chunk, run /shops reload, and restart the server. The
transient text entity should disappear while unloaded and be recreated once for
the saved anchor afterward, together with exactly one transient landmark item.
Change profile text and create or remove an eligible shop, then wait for the
catalogue refresh and confirm the panel updates. Block and clear the space above
it and confirm the panel, landmark, and particles follow the obstruction.
Set an 80-character advertisement and confirm it wraps onto no more than two
panel lines without the old early truncation. Change storefront-display.panel.width,
storefront-display.panel.vertical-offset,
storefront-display.icon.vertical-offset, icon height, material, scale,
periods, view distance, particle type, color, size, radius, and count with
/shops config set; each change should apply live without moving ordinary shop holograms.
Disable the icon and particle layers separately and verify that no stale entity
or effect remains. In a dense area, confirm each viewer receives particles from
at most the six nearest active Storefront Displays.
Right-click the title, middle, and footer areas of the panel and confirm each
opens /shops profile shopowner <owner>. Rapidly click the same panel and
alternate between multiple panels; only one profile load per player should be
accepted within storefront-display.interaction.cooldown-milliseconds.
Off-hand packets must not trigger a second load. Disable
storefront-display.interaction.enabled live and confirm the invisible hitbox
is removed, then enable it again. Unload the chunk and verify both the text and
interaction entity disappear.
Suspend and unsuspend the storefront. Suspension must hide the text while
retaining the anchor; unsuspension restores it. Verify
/shops admin storefront <player> display remove releases the owner's allowance.
Place again, then break the Ender Chest through an otherwise permitted block
break and confirm the record is cleaned up. Finally, use
/shops profile display remove and confirm it removes only the display, leaving
the Ender Chest, profile, Featured Listings, ordinary shops, and advertising
state unchanged.
Run these equivalent searches:
/shops search stone_bricks
/shops search stone bricks
/shops search minecraft:stone_bricks
/shops search stone_bricks 2
Verify exact material resolution, stable four-row pagination, bundle and unit prices, full-bundle availability, storefront links, and owner interleaving. The summary should mention the out-of-stock shop. It must not list the admin shop, customer-sell-only shop, suspended owner, or outside-region shop.
Unload a candidate shop chunk and search again after the previous snapshot
expires. It should remain on the result pages after all verified-stock rows,
with a yellow STOCK UNCHECKED label and the registered-offer explanation,
without loading the chunk. Visit its displayed location, search again, and
confirm the row changes to a verified bundle count or moves to the out-of-stock
count according to its chest contents. Remove the complete configured bundle
from one loaded shop and confirm it moves from the result rows to the
out-of-stock count. Stock an item with the same material but different metadata
and verify that it does not satisfy the exact configured variant.
Misspell a material, such as /shops search stone_briks, and confirm no fuzzy
results appear. At most three clickable suggestions may be offered, and every
suggestion must be an exact material currently sold by a public Customer-Buy
Offer.
Repeat a search immediately to confirm rate limiting. Navigate an existing
result's next/previous links and confirm it reuses a stable snapshot. As staff
with shopchest.admin.list, verify a listed coordinate is clickable and the
target/permission are revalidated. Remove the permission before clicking a
cached row and confirm teleport is denied.
Temporarily set storefront-discovery.location-scope to GLOBAL, reload, and
confirm the outside-region normal shop becomes discoverable but still does not
give ordinary players a teleport action. Restore MARKETPLACE afterward.
Prepare these inventory fixtures beside genuine tokens:
- plain
LIGHT_BLUE_DYE; - a dye renamed to the token's visible name;
- an item with copied name and lore;
- token-like items with missing, additional, and changed PDC/components.
Run /shops advertise pass. Its preview should count only genuine stacks that
pass complete amount-normalized ItemStack.isSimilar matching. Confirm that a
stack spread over multiple storage slots is counted and that armor/offhand
slots are not treated as payment storage.
Click the generated confirmation once. Verify exactly the configured number of genuine tokens is removed and no lookalike changes. Click the same confirmation again and confirm it cannot execute twice. Try an expired confirmation, too few tokens, two rapid confirmations, and an already active pass. None may create a second pass or consume extra items.
In a controlled failure-injection test, fail pass persistence after exact stack removal. Confirm the exact removed items, including their metadata/components, return and the player can retry only after recovery. Also exercise a full or concurrently changed inventory and verify ShopChest logs an explicit manual recovery condition instead of substituting or duplicating items.
Run /shops admin advertise currency clear and confirm the template file is
removed, status reports fail-closed state, and purchases consume nothing.
Recapture the genuine token before continuing.
With an active pass and restored Featured Listings, run:
/shops advertise
/shops advertise status
Verify the preview uses the first Featured Listing as primary and includes only in-stock support listings. Remove the primary bundle and confirm queueing is refused. Restock it, open a new preview, and confirm the request. Confirm there is at most one open request and that status shows its eligibility.
Queue eligible requests from two owners. For a shorter test, temporarily set
advertising.global-cooldown-minutes to 1, reload, and restore 30 after the
test. Verify FIFO eligible order and at least one minute between title/chat/sound
broadcasts. A successful message should link both the seller profile and
/warp shops, and decrement exactly one use.
With only five players online, confirm an eligible request stays queued, status
shows 5/6, and no pass use or owner/global cooldown begins. Bring a sixth
player online and confirm the next eligible queue poll can broadcast exactly
once. Restore advertising.minimum-online-players to 6 if it was changed.
After one owner broadcasts, confirm a new request respects the configured owner
cooldown. Cancel a waiting request with /shops advertise cancel; its reserved
use should return. Make a queued primary temporarily out of stock and confirm
it waits rather than spends a use. Restore stock and verify a later poll can
broadcast it. Exercise request expiry on disposable data and verify the
reservation returns.
Run:
/shops admin export marketplace
Verify the JSON and CSV pair appears under
plugins/ShopChest/exports/marketplace/. Confirm both carry the same capture
time, display timezone, source version, schema version, aggregate candidate and
availability counts, banner, and listing data. Check that
only marketplace-region normal customer-buy shops are present, including their
captured in-stock/out-of-stock/unchecked state.
Search the files for UUIDs, exact coordinates, shop IDs, database row numbers, inventory contents, balances, token data, and private moderation data. None should be present. Open the CSV with a formula-prefixed public fixture and confirm it is neutralized. Confirm JSON public text is escaped rather than interpreted as markup.
Finally, review and copy the pair into docs/catalogue/, run the docs validation
and build, and open the website page. Search by owner name, storefront name,
item name, and material. The capture banner must stay prominent and explain
that prices and stock may have changed.
Before handing the test server back, restore:
/shops config set storefront-discovery.location-scope MARKETPLACE
/shops config set advertising.global-cooldown-minutes 30
/shops reload
Run currency status, profile, search, advertise status, and one final export. Record any intentionally queued request so another tester does not mistake it for a duplicate.