Skip to content

Om 405 - #80

Merged
SebaKisser merged 8 commits into
devfrom
OM-405
Apr 7, 2026
Merged

SebaKisser merged 8 commits into
devfrom
OM-405

Conversation

@J-Kanami-PS

@J-Kanami-PS J-Kanami-PS commented Apr 6, 2026 •

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • Nuevas Funcionalidades

    • Vendedores pueden activar/desactivar su tienda vía endpoint autenticado.
    • Vendedores pueden consultar sus propios datos de tienda aun cuando estén inactivos.
    • Cuando se cambia el estado de la tienda, los productos se sincronizan (visibilidad).
  • Mejoras

    • La vista pública de tiendas sólo muestra comercios activos.
  • Tests

    • Se agregaron pruebas que cubren consultas públicas, acceso del vendedor y cambios de estado.

@coderabbitai

coderabbitai Bot commented Apr 6, 2026 •

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

Se añaden dos endpoints autenticados (obtener tienda del propio usuario y actualizar estado de tienda), se ajusta la lógica de obtención pública de tienda para ignorar la verificación de estado y se introduce lógica de servicio para gestionar store_status y sincronizar visibilidad de productos; además se agregan tests que cubren estos flujos.

Changes

Cohort / File(s) Summary
Controlador de tienda
src/modules/commerce/commerces/store.controller.js
Se añadió getMyStore (GET /api/commerces/my/:id) y updateStoreStatus (PATCH /api/commerces/:id/status); getStoreById deja de lanzar 404 por estado y siempre devuelve el resultado del servicio.
Rutas de tienda
src/modules/commerce/commerces/store.routes.js
Se registraron rutas autenticadas GET /api/commerces/my/:id y PATCH /api/commerces/:id/status, con /my/:id insertada antes de /:id para evitar colisiones.
Servicio de tienda
src/modules/commerce/commerces/store.service.js
getStoreByIdService ahora acepta { ignoreStoreStatus = false } y selecciona store_status; cuando ignoreStoreStatus es false se rechaza tiendas no ACTIVE. Se agregó updateStoreStatusService que valida autorización y store_status, actualiza stores.store_status y sincroniza products.visible dentro de una transacción. getStoresService ahora filtra por store_status: "ACTIVE".
Tests
tests/unit/commerce/store-status.test.js
Nuevo conjunto de tests unitarios que mockean Prisma y JWT para validar comportamiento público, autenticado y actualización de store_status en múltiples escenarios.

Diagramas de secuencia

sequenceDiagram
    participant Client
    participant Controller
    participant Service
    participant Database

    Client->>Controller: PATCH /api/commerces/:id/status (auth, store_status)
    Controller->>Service: updateStoreStatusService(userId, storeId, store_status)
    Service->>Service: Validar store_status (ACTIVE|INACTIVE)
    Service->>Service: getAuthorizedStoreOwnerService(userId, storeId)
    Service->>Database: prisma.$transaction([update stores, update products, select store])
    Database-->>Service: Resultado transacción (tienda actualizada)
    Service-->>Controller: { success, message, data }
    Controller-->>Client: 200 OK
Loading
sequenceDiagram
    participant Client
    participant Controller
    participant Service
    participant Database

    Client->>Controller: GET /api/commerces/my/:id (auth)
    Controller->>Service: getStoreByIdService(id, {ignoreStoreStatus:true})
    Service->>Database: SELECT tienda (incluye store_status)
    Database-->>Service: Datos de tienda
    Service-->>Controller: Tienda obtenida
    Controller->>Controller: Verificar propiedad (store.user.id_user === req.user.id_user)
    alt Propietario válido
        Controller-->>Client: 200 OK (tienda)
    else No autorizado
        Controller-->>Client: 403 Forbidden
    end
Loading

Estimated code review effort

🎯 4 (Complexo) | ⏱️ ~50 minutes

Possibly related PRs

  • Om 55: Merging with Cris Code rabbit #15: Modifica las mismas funciones de controlador/servicio relacionadas con getStoreById y rutas de tienda.
  • Om 301 #53: Introduce/gestiona el campo store_status en la base de datos, relacionado directamente con la nueva lógica de estado.
  • Arreglar/juntar los PRs #28: Cambios superpuestos en getStoreByIdService (selección/forma de retorno y comportamiento según estado).

Suggested reviewers

  • leoAchu16
  • CrisNAC
  • Andoumeda

Poema

"Soy un conejito que salta y prueba,
cambio rutas, estados y una nueva estrella,
sincronizo productos cuando la tienda despierta,
propietario verifica, la seguridad está completa. 🐇✨"

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive El título 'Om 405' es vago y no describe con claridad el cambio principal. No comunica información sobre las nuevas funcionalidades de gestión de estado de tienda añadidas. Reemplazar con un título descriptivo que resuma el cambio principal, por ejemplo: 'Add store status management endpoints and authorization'.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch OM-405

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/modules/commerce/commerces/store.service.js (1)

826-833: ⚠️ Potential issue | 🟠 Major

Seguí ocultando comercios con status: false.

deleteStoreService hace borrado lógico con status = false, pero acá sólo se rechaza store_status !== "ACTIVE". Si una tienda quedó ACTIVE y después se borró lógicamente, GET /api/commerces/:id la vuelve a exponer.

🩹 Ajuste mínimo
     if (!store) {
       throw { status: 404, message: "Comercio no encontrado" };
     }
+    if (!store.status) {
+      throw { status: 404, message: "Comercio no encontrado" };
+    }
 
     // Solo bloquear a clientes — el SELLER puede ver su comercio aunque esté INACTIVE
     if (!ignoreStoreStatus && store.store_status !== "ACTIVE") {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/modules/commerce/commerces/store.service.js` around lines 826 - 833, The
handler currently only checks store.store_status but ignores the
logical-deletion flag store.status used by deleteStoreService, so a
logically-deleted store can still be returned; update the conditional in the
same block (the branch that checks ignoreStoreStatus and store.store_status !==
"ACTIVE") to also treat store.status === false as not available (i.e., throw the
same 404 "Comercio no disponible") unless ignoreStoreStatus is true; reference
the deleteStoreService logical-delete behavior and the variables store.status,
store.store_status and ignoreStoreStatus when making the change.
🧹 Nitpick comments (2)
src/modules/commerce/commerces/store.routes.js (1)

161-162: El orden de rutas está bien, pero faltan los bloques Swagger.

Sin anotaciones para /api/commerces/my/{id} y /api/commerces/{id}/status, la spec queda incompleta y Swagger UI no los muestra.

Also applies to: 315-316

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/modules/commerce/commerces/store.routes.js` around lines 161 - 162,
Agregar bloques de documentación Swagger/OpenAPI para las rutas que faltan: la
ruta autenticada router.get("/my/:id", authenticate, getMyStore) (endpoint
/api/commerces/my/{id}) y la ruta de estado router.patch("/:id/status",
authenticate, updateStoreStatus) (endpoint /api/commerces/{id}/status) — incluye
tags, summary, description, parameters (path id), security (bearerAuth si
aplica), requestBody/schema para el patch si requiere payload, y respuestas
(200, 400, 401, 404, 500) con ejemplos; coloca estas anotaciones JSDoc justo
encima de las declaraciones de ruta para que Swagger genere ambas operaciones en
la spec.
src/modules/commerce/commerces/store.controller.js (1)

69-71: Saquen el código comentado del flujo anterior.

Ahora la disponibilidad del comercio se resuelve en el service; dejar esta validación vieja comentada al lado del return 200 agrega ruido y confunde dónde vive la regla.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/modules/commerce/commerces/store.controller.js` around lines 69 - 71,
Quitar el bloque comentado que valida "store" y "store.status" (las líneas "//if
(!store || !store.status) { //throw { status: 404, message: "Comercio no
encontrado" }; //}") del controlador (en el método que termina con el "return
200") porque la disponibilidad ahora se resuelve en el service; elimina esas
líneas comentadas para evitar ruido y dejar solo el flujo que devuelve 200.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/modules/commerce/commerces/store.controller.js`:
- Around line 88-89: The owner check compares store.user.id_user (a numeric
Prisma ID) with req.user.id_user (a string from the JWT), causing legitimate
owners to be rejected; update the condition to compare like types—e.g., cast
req.user.id_user to Number or cast store.user.id_user to String—so change the
guard using store.user?.id_user !== Number(req.user?.id_user) (or
Number(req.user.id_user) where used) and keep the same null-safe accessors
(store.user?.id_user and req.user?.id_user) to avoid runtime errors.

In `@src/modules/commerce/commerces/store.service.js`:
- Around line 1076-1085: The transaction is overwriting products.visible based
on store_status (see prisma.stores.update and prisma.products.updateMany) which
destroys seller preferences; stop mutating products.visible in store status
changes and instead enforce public gating based on stores.store_status
(store_status) or introduce a dedicated flag (e.g., products.hidden_by_store) if
you need a reversible store-level override; update any consumers (notably
getAllProductsByStoreService) to filter or gate results by the store's status
(or by the new dedicated flag) rather than relying on products.visible being
toggled.

In `@src/server.js`:
- Line 3: Eliminar el console.log que imprime process.env.DATABASE_URL en
src/server.js (la llamada console.log("DATABASE_URL:",
process.env.DATABASE_URL)); en su lugar omitir la impresión de esa variable
sensible o loguear una versión enmascarada (por ejemplo solo indicar que existe
o mostrar host sin credenciales) para evitar exponer usuario/contraseña en logs;
busca la llamada a console.log que referencia process.env.DATABASE_URL y
reemplázala/elimínala siguiendo la política de no loguear secretos.

---

Outside diff comments:
In `@src/modules/commerce/commerces/store.service.js`:
- Around line 826-833: The handler currently only checks store.store_status but
ignores the logical-deletion flag store.status used by deleteStoreService, so a
logically-deleted store can still be returned; update the conditional in the
same block (the branch that checks ignoreStoreStatus and store.store_status !==
"ACTIVE") to also treat store.status === false as not available (i.e., throw the
same 404 "Comercio no disponible") unless ignoreStoreStatus is true; reference
the deleteStoreService logical-delete behavior and the variables store.status,
store.store_status and ignoreStoreStatus when making the change.

---

Nitpick comments:
In `@src/modules/commerce/commerces/store.controller.js`:
- Around line 69-71: Quitar el bloque comentado que valida "store" y
"store.status" (las líneas "//if (!store || !store.status) { //throw { status:
404, message: "Comercio no encontrado" }; //}") del controlador (en el método
que termina con el "return 200") porque la disponibilidad ahora se resuelve en
el service; elimina esas líneas comentadas para evitar ruido y dejar solo el
flujo que devuelve 200.

In `@src/modules/commerce/commerces/store.routes.js`:
- Around line 161-162: Agregar bloques de documentación Swagger/OpenAPI para las
rutas que faltan: la ruta autenticada router.get("/my/:id", authenticate,
getMyStore) (endpoint /api/commerces/my/{id}) y la ruta de estado
router.patch("/:id/status", authenticate, updateStoreStatus) (endpoint
/api/commerces/{id}/status) — incluye tags, summary, description, parameters
(path id), security (bearerAuth si aplica), requestBody/schema para el patch si
requiere payload, y respuestas (200, 400, 401, 404, 500) con ejemplos; coloca
estas anotaciones JSDoc justo encima de las declaraciones de ruta para que
Swagger genere ambas operaciones en la spec.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 87c37045-4925-47f5-b761-e2e35ebc0c07

📥 Commits

Reviewing files that changed from the base of the PR and between 179019d and 3fb53a1.

📒 Files selected for processing (4)
  • src/modules/commerce/commerces/store.controller.js
  • src/modules/commerce/commerces/store.routes.js
  • src/modules/commerce/commerces/store.service.js
  • src/server.js

Comment on lines +88 to +89
if (store.user?.id_user !== req.user?.id_user) {
return res.status(403).json({ message: "No tenés permisos para ver este comercio" });

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== authenticate middleware ==\n'
fd -p 'jwt.config.js' src | xargs -r sed -n '1,220p'

printf '\n== usos de req.user.id_user ==\n'
rg -n -C2 '\breq\.user\??\.id_user\b' src

Repository: CrisNAC/BackendMarketplace

Length of output: 19504


Verificá el tipo antes de comparar el owner con !==.

store.user.id_user sale numérico de Prisma, pero req.user.id_user viene como string desde el JWT (como se ve en la línea 25 del mismo archivo con Number(req.user.id_user)). Sin casteo, el dueño legítimo cae en 403 por diferencia de tipo.

Ajuste requerido
-    if (store.user?.id_user !== req.user?.id_user) {
+    if (Number(store.user?.id_user) !== Number(req.user?.id_user)) {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (store.user?.id_user !== req.user?.id_user) {
return res.status(403).json({ message: "No tenés permisos para ver este comercio" });
if (Number(store.user?.id_user) !== Number(req.user?.id_user)) {
return res.status(403).json({ message: "No tenés permisos para ver este comercio" });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/modules/commerce/commerces/store.controller.js` around lines 88 - 89, The
owner check compares store.user.id_user (a numeric Prisma ID) with
req.user.id_user (a string from the JWT), causing legitimate owners to be
rejected; update the condition to compare like types—e.g., cast req.user.id_user
to Number or cast store.user.id_user to String—so change the guard using
store.user?.id_user !== Number(req.user?.id_user) (or Number(req.user.id_user)
where used) and keep the same null-safe accessors (store.user?.id_user and
req.user?.id_user) to avoid runtime errors.

Comment on lines +1076 to +1085
await prisma.$transaction([
prisma.stores.update({
where: { id_store: store.id_store },
data: { store_status }
}),
// Al desactivar → ocultar productos. Al activar → hacerlos visibles nuevamente.
prisma.products.updateMany({
where: { fk_store: store.id_store, status: true },
data: { visible: store_status === "ACTIVE" }
})

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

No pisen products.visible para reflejar store_status.

Al desactivar guardás visible = false en todos los productos y al reactivar los dejás todos en true. Eso borra la preferencia real del vendedor; además getAllProductsByStoreService no filtra visible, así que esta sincronización tampoco garantiza ocultarlos. El gating público debería depender de stores.status/store_status, o de un flag separado.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/modules/commerce/commerces/store.service.js` around lines 1076 - 1085,
The transaction is overwriting products.visible based on store_status (see
prisma.stores.update and prisma.products.updateMany) which destroys seller
preferences; stop mutating products.visible in store status changes and instead
enforce public gating based on stores.store_status (store_status) or introduce a
dedicated flag (e.g., products.hidden_by_store) if you need a reversible
store-level override; update any consumers (notably
getAllProductsByStoreService) to filter or gate results by the store's status
(or by the new dedicated flag) rather than relying on products.visible being
toggled.

Comment thread src/server.js Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/unit/commerce/store-status.test.js`:
- Around line 166-205: The tests verify HTTP status and messages but don't
assert that product visibility is updated; add assertions that
prisma.products.updateMany was called with the correct args when toggling the
store status: in the "deshabilitar" test expect(prisma.products.updateMany) to
have been called with where: { store_id: 1 } and data: { visible: false }, and
in the "habilitar" test expect(prisma.products.updateMany) to have been called
with data: { visible: true }; reference the mocked prisma.products.updateMany
call in these tests (and ensure it's been mocked/resolved) so the
/api/commerces/1/status flow is validated end-to-end.
- Around line 20-30: El mock de jsonwebtoken debe soportar tanto el uso síncrono
como el asincrónico con callback: modifica la implementación de verify en el
mock (donde se crea vi.mock y se retorna default) para que la función
vi.fn((token, secret, callback) => { ... }) detecte si callback es una función;
si lo es, llama callback(null, payload) y si no, simplemente devuelva el payload
({ id_user: 1, email: "test@test.com", role: "SELLER" }), de modo que llamadas a
jwt.verify(token, secret) en store.controller.js (uso síncrono) y
jwt.verify(token, secret, cb) (callback) funcionen correctamente.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2b2d4b54-36ec-46f3-8802-fa4382698a72

📥 Commits

Reviewing files that changed from the base of the PR and between 0ceecd0 and 3d80511.

📒 Files selected for processing (1)
  • tests/unit/commerce/store-status.test.js

Comment on lines +20 to +30
vi.mock("jsonwebtoken", async () => {
const actual = await vi.importActual("jsonwebtoken");
return {
default: {
...actual.default,
verify: vi.fn((token, secret, callback) => {
callback(null, { id_user: 1, email: "test@test.com", role: "SELLER" });
}),
}
};
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verifica cómo se usa jsonwebtoken.verify en el repo (callback vs sync)
rg -n -C3 --type=js --type=ts 'from\s+["'"'"']jsonwebtoken["'"'"']|require\(["'"'"']jsonwebtoken["'"'"']\)'
rg -n -C3 --type=js --type=ts '\.verify\s*\('

Repository: CrisNAC/BackendMarketplace

Length of output: 4683


Hacé compatible el mock de jwt.verify con modo síncrono y callback.

El store.controller.js usa jwt.verify(token, secret) en forma síncrona (línea 192), pero el mock actual solo soporta callback. Esto causará que el test falle.

💡 Ajuste propuesto
 vi.mock("jsonwebtoken", async () => {
     const actual = await vi.importActual("jsonwebtoken");
+    const mockPayload = { id_user: 1, email: "test@test.com", role: "SELLER" };
     return {
         default: {
             ...actual.default,
             verify: vi.fn((token, secret, callback) => {
-                callback(null, { id_user: 1, email: "test@test.com", role: "SELLER" });
+                if (typeof callback === "function") {
+                    callback(null, mockPayload);
+                    return;
+                }
+                return mockPayload;
             }),
         }
     };
 });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
vi.mock("jsonwebtoken", async () => {
const actual = await vi.importActual("jsonwebtoken");
return {
default: {
...actual.default,
verify: vi.fn((token, secret, callback) => {
callback(null, { id_user: 1, email: "test@test.com", role: "SELLER" });
}),
}
};
});
vi.mock("jsonwebtoken", async () => {
const actual = await vi.importActual("jsonwebtoken");
const mockPayload = { id_user: 1, email: "test@test.com", role: "SELLER" };
return {
default: {
...actual.default,
verify: vi.fn((token, secret, callback) => {
if (typeof callback === "function") {
callback(null, mockPayload);
return;
}
return mockPayload;
}),
}
};
});
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/unit/commerce/store-status.test.js` around lines 20 - 30, El mock de
jsonwebtoken debe soportar tanto el uso síncrono como el asincrónico con
callback: modifica la implementación de verify en el mock (donde se crea vi.mock
y se retorna default) para que la función vi.fn((token, secret, callback) => {
... }) detecte si callback es una función; si lo es, llama callback(null,
payload) y si no, simplemente devuelva el payload ({ id_user: 1, email:
"test@test.com", role: "SELLER" }), de modo que llamadas a jwt.verify(token,
secret) en store.controller.js (uso síncrono) y jwt.verify(token, secret, cb)
(callback) funcionen correctamente.

Comment on lines +166 to +205
it("devuelve 200 y mensaje correcto al deshabilitar el comercio", async () => {
prisma.stores.findUnique
.mockResolvedValueOnce(mockActiveStore)
.mockResolvedValueOnce({
id_store: 1,
name: "Comercio Test",
store_status: "INACTIVE",
status: true,
});
prisma.$transaction.mockResolvedValue([{}, {}]);

const res = await request(app)
.patch("/api/commerces/1/status")
.set("Cookie", authCookie)
.send({ store_status: "INACTIVE" });

expect(res.status).toBe(200);
expect(res.body.message).toMatch(/deshabilitado/i);
expect(res.body.success).toBe(true);
});

it("devuelve 200 y mensaje correcto al habilitar el comercio", async () => {
prisma.stores.findUnique
.mockResolvedValueOnce(mockInactiveStore)
.mockResolvedValueOnce({
id_store: 1,
name: "Comercio Test",
store_status: "ACTIVE",
status: true,
});
prisma.$transaction.mockResolvedValue([{}, {}]);

const res = await request(app)
.patch("/api/commerces/1/status")
.set("Cookie", authCookie)
.send({ store_status: "ACTIVE" });

expect(res.status).toBe(200);
expect(res.body.message).toMatch(/habilitado/i);
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Falta asertar el efecto clave sobre visibilidad de productos en el toggle de estado.

Estos tests validan status/mensaje, pero no verifican explícitamente que el cambio ACTIVE/INACTIVE impacte visible en productos, que es parte central del flujo.

✅ Aserciones sugeridas
         expect(res.status).toBe(200);
         expect(res.body.message).toMatch(/deshabilitado/i);
         expect(res.body.success).toBe(true);
+        expect(prisma.products.updateMany).toHaveBeenCalledWith(
+            expect.objectContaining({ data: { visible: false } })
+        );

         expect(res.status).toBe(200);
         expect(res.body.message).toMatch(/habilitado/i);
+        expect(prisma.products.updateMany).toHaveBeenCalledWith(
+            expect.objectContaining({ data: { visible: true } })
+        );
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
it("devuelve 200 y mensaje correcto al deshabilitar el comercio", async () => {
prisma.stores.findUnique
.mockResolvedValueOnce(mockActiveStore)
.mockResolvedValueOnce({
id_store: 1,
name: "Comercio Test",
store_status: "INACTIVE",
status: true,
});
prisma.$transaction.mockResolvedValue([{}, {}]);
const res = await request(app)
.patch("/api/commerces/1/status")
.set("Cookie", authCookie)
.send({ store_status: "INACTIVE" });
expect(res.status).toBe(200);
expect(res.body.message).toMatch(/deshabilitado/i);
expect(res.body.success).toBe(true);
});
it("devuelve 200 y mensaje correcto al habilitar el comercio", async () => {
prisma.stores.findUnique
.mockResolvedValueOnce(mockInactiveStore)
.mockResolvedValueOnce({
id_store: 1,
name: "Comercio Test",
store_status: "ACTIVE",
status: true,
});
prisma.$transaction.mockResolvedValue([{}, {}]);
const res = await request(app)
.patch("/api/commerces/1/status")
.set("Cookie", authCookie)
.send({ store_status: "ACTIVE" });
expect(res.status).toBe(200);
expect(res.body.message).toMatch(/habilitado/i);
});
it("devuelve 200 y mensaje correcto al deshabilitar el comercio", async () => {
prisma.stores.findUnique
.mockResolvedValueOnce(mockActiveStore)
.mockResolvedValueOnce({
id_store: 1,
name: "Comercio Test",
store_status: "INACTIVE",
status: true,
});
prisma.$transaction.mockResolvedValue([{}, {}]);
const res = await request(app)
.patch("/api/commerces/1/status")
.set("Cookie", authCookie)
.send({ store_status: "INACTIVE" });
expect(res.status).toBe(200);
expect(res.body.message).toMatch(/deshabilitado/i);
expect(res.body.success).toBe(true);
expect(prisma.products.updateMany).toHaveBeenCalledWith(
expect.objectContaining({ data: { visible: false } })
);
});
it("devuelve 200 y mensaje correcto al habilitar el comercio", async () => {
prisma.stores.findUnique
.mockResolvedValueOnce(mockInactiveStore)
.mockResolvedValueOnce({
id_store: 1,
name: "Comercio Test",
store_status: "ACTIVE",
status: true,
});
prisma.$transaction.mockResolvedValue([{}, {}]);
const res = await request(app)
.patch("/api/commerces/1/status")
.set("Cookie", authCookie)
.send({ store_status: "ACTIVE" });
expect(res.status).toBe(200);
expect(res.body.message).toMatch(/habilitado/i);
expect(prisma.products.updateMany).toHaveBeenCalledWith(
expect.objectContaining({ data: { visible: true } })
);
});
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/unit/commerce/store-status.test.js` around lines 166 - 205, The tests
verify HTTP status and messages but don't assert that product visibility is
updated; add assertions that prisma.products.updateMany was called with the
correct args when toggling the store status: in the "deshabilitar" test
expect(prisma.products.updateMany) to have been called with where: { store_id: 1
} and data: { visible: false }, and in the "habilitar" test
expect(prisma.products.updateMany) to have been called with data: { visible:
true }; reference the mocked prisma.products.updateMany call in these tests (and
ensure it's been mocked/resolved) so the /api/commerces/1/status flow is
validated end-to-end.

@SebaKisser
SebaKisser merged commit 47d0a83 into dev Apr 7, 2026
2 checks passed
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