1- import { afterEach , beforeEach , describe , expect , it , vi } from 'vitest' ;
1+ import { beforeEach , describe , expect , it , vi } from 'vitest' ;
22import { cookies , headers } from 'next/headers' ;
33import { getSupabaseServerClient } from '@/infra/integrations/supabase' ;
4- import {
5- getPopularViewsInRecentDays ,
6- getViewCount ,
7- incrementView ,
8- trackView ,
9- } from './view' ;
4+ import { getViewCount , incrementView , trackView } from './view' ;
105
116vi . mock ( '@/infra/integrations/supabase' , ( ) => ( {
127 getSupabaseServerClient : vi . fn ( ) ,
@@ -28,9 +23,6 @@ type SupabaseLike = {
2823 __queryMock : {
2924 select : ReturnType < typeof vi . fn > ;
3025 eq : ReturnType < typeof vi . fn > ;
31- gte : ReturnType < typeof vi . fn > ;
32- order : ReturnType < typeof vi . fn > ;
33- limit : ReturnType < typeof vi . fn > ;
3426 maybeSingle : ReturnType < typeof vi . fn > ;
3527 } ;
3628} ;
@@ -51,9 +43,6 @@ function createQueryMock(payload: {
5143 return {
5244 select : vi . fn ( ) . mockReturnThis ( ) ,
5345 eq : vi . fn ( ) . mockReturnThis ( ) ,
54- gte : vi . fn ( ) . mockReturnThis ( ) ,
55- order : vi . fn ( ) . mockReturnThis ( ) ,
56- limit : vi . fn ( ) . mockResolvedValue ( payload ) ,
5746 maybeSingle : vi . fn ( ) . mockResolvedValue ( payload ) ,
5847 } ;
5948}
@@ -78,23 +67,6 @@ function createSupabaseMock(options: {
7867const mockedGetSupabase = vi . mocked ( getSupabaseServerClient ) ;
7968const mockedCookies = vi . mocked ( cookies ) ;
8069const mockedHeaders = vi . mocked ( headers ) ;
81- const originalNextPhase = process . env . NEXT_PHASE ;
82- const originalNpmLifecycleEvent = process . env . npm_lifecycle_event ;
83-
84- function restoreBuildPhaseEnv ( ) {
85- if ( originalNextPhase === undefined ) {
86- delete process . env . NEXT_PHASE ;
87- } else {
88- process . env . NEXT_PHASE = originalNextPhase ;
89- }
90-
91- if ( originalNpmLifecycleEvent === undefined ) {
92- delete process . env . npm_lifecycle_event ;
93- } else {
94- process . env . npm_lifecycle_event = originalNpmLifecycleEvent ;
95- }
96- }
97-
9870function createCookieStoreMock (
9971 visitorId : string | null = null
10072) : CookieStoreLike {
@@ -118,7 +90,6 @@ function createHeaderStoreMock(
11890
11991describe ( 'view actions' , ( ) => {
12092 beforeEach ( ( ) => {
121- restoreBuildPhaseEnv ( ) ;
12293 vi . clearAllMocks ( ) ;
12394 mockedCookies . mockResolvedValue ( createCookieStoreMock ( ) ) ;
12495 mockedHeaders . mockResolvedValue (
@@ -130,10 +101,6 @@ describe('view actions', () => {
130101 ) ;
131102 } ) ;
132103
133- afterEach ( ( ) => {
134- restoreBuildPhaseEnv ( ) ;
135- } ) ;
136-
137104 it ( 'increments view when slug is valid and client exists' , async ( ) => {
138105 const client = createSupabaseMock ( {
139106 queryPayload : { data : { count : 10 } , error : null } ,
@@ -358,93 +325,4 @@ describe('view actions', () => {
358325 } )
359326 ) ;
360327 } ) ;
361-
362- it ( 'fetches recent daily view totals through the popular views rpc' , async ( ) => {
363- const client = createSupabaseMock ( {
364- queryPayload : { data : null , error : null } ,
365- rpcPayload : {
366- data : [
367- {
368- slug : 'a' ,
369- count : 10 ,
370- updated_at : '2026-03-05T00:00:00.000Z' ,
371- } ,
372- {
373- slug : 'b' ,
374- count : 10 ,
375- updated_at : '2026-03-04T00:00:00.000Z' ,
376- } ,
377- ] ,
378- error : null ,
379- } ,
380- } ) ;
381- mockedGetSupabase . mockReturnValue ( client ) ;
382-
383- const result = await getPopularViewsInRecentDays ( 30 , 5 ) ;
384-
385- expect ( client . rpc ) . toHaveBeenCalledWith ( 'get_popular_views' , {
386- days_input : 30 ,
387- limit_input : 5 ,
388- } ) ;
389- expect ( result ) . toEqual ( [
390- { slug : 'a' , count : 10 , updated_at : '2026-03-05T00:00:00.000Z' } ,
391- { slug : 'b' , count : 10 , updated_at : '2026-03-04T00:00:00.000Z' } ,
392- ] ) ;
393- } ) ;
394-
395- it ( 'returns empty list when supabase is unavailable for popular query' , async ( ) => {
396- mockedGetSupabase . mockReturnValue ( null ) ;
397-
398- const result = await getPopularViewsInRecentDays ( 30 , 5 ) ;
399-
400- expect ( result ) . toEqual ( [ ] ) ;
401- } ) ;
402-
403- it ( 'returns empty list when popular query fails' , async ( ) => {
404- const client = createSupabaseMock ( {
405- queryPayload : { data : null , error : null } ,
406- rpcPayload : {
407- data : null ,
408- error : { message : 'failed' } ,
409- } ,
410- } ) ;
411- mockedGetSupabase . mockReturnValue ( client ) ;
412-
413- const result = await getPopularViewsInRecentDays ( 30 , 5 ) ;
414-
415- expect ( result ) . toEqual ( [ ] ) ;
416- } ) ;
417-
418- it ( 'skips popular query during production build phase' , async ( ) => {
419- process . env . NEXT_PHASE = 'phase-production-build' ;
420- mockedGetSupabase . mockReturnValue (
421- createSupabaseMock ( {
422- queryPayload : {
423- data : [ { slug : 'a' , count : 10 , updated_at : '2026-03-05' } ] ,
424- error : null ,
425- } ,
426- rpcPayload : { data : 0 , error : null } ,
427- } )
428- ) ;
429-
430- const result = await getPopularViewsInRecentDays ( 30 , 5 ) ;
431-
432- expect ( result ) . toEqual ( [ ] ) ;
433- expect ( mockedGetSupabase ) . not . toHaveBeenCalled ( ) ;
434- } ) ;
435-
436- it ( 'normalizes invalid day/limit inputs for popular query' , async ( ) => {
437- const client = createSupabaseMock ( {
438- queryPayload : { data : null , error : null } ,
439- rpcPayload : { data : [ ] , error : null } ,
440- } ) ;
441- mockedGetSupabase . mockReturnValue ( client ) ;
442-
443- await getPopularViewsInRecentDays ( 0 , 0 ) ;
444-
445- expect ( client . rpc ) . toHaveBeenCalledWith ( 'get_popular_views' , {
446- days_input : 1 ,
447- limit_input : 1 ,
448- } ) ;
449- } ) ;
450328} ) ;
0 commit comments