Repository navigation
Om 405 - #80
Om 405#80
Conversation
📝 WalkthroughWalkthroughSe 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 Changes
Diagramas de secuenciasequenceDiagram
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
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
Estimated code review effort🎯 4 (Complexo) | ⏱️ ~50 minutes Possibly related PRs
Suggested reviewers
Poema
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
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 | 🟠 MajorSeguí ocultando comercios con
status: false.
deleteStoreServicehace borrado lógico constatus = false, pero acá sólo se rechazastore_status !== "ACTIVE". Si una tienda quedóACTIVEy después se borró lógicamente,GET /api/commerces/:idla 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 200agrega 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
📒 Files selected for processing (4)
src/modules/commerce/commerces/store.controller.jssrc/modules/commerce/commerces/store.routes.jssrc/modules/commerce/commerces/store.service.jssrc/server.js
| if (store.user?.id_user !== req.user?.id_user) { | ||
| return res.status(403).json({ message: "No tenés permisos para ver este comercio" }); |
There was a problem hiding this comment.
🧩 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' srcRepository: 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.
| 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.
| 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" } | ||
| }) |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
📒 Files selected for processing (1)
tests/unit/commerce/store-status.test.js
| 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" }); | ||
| }), | ||
| } | ||
| }; | ||
| }); |
There was a problem hiding this comment.
🧩 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.
| 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.
| 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); | ||
| }); |
There was a problem hiding this comment.
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.
| 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.
Summary by CodeRabbit
Nuevas Funcionalidades
Mejoras
Tests