1+ /****************************************************************************
2+ * Copyright 2025, Optimizely, Inc. and contributors *
3+ * *
4+ * Licensed under the Apache License, Version 2.0 (the "License"); *
5+ * you may not use this file except in compliance with the License. *
6+ * You may obtain a copy of the License at *
7+ * *
8+ * http://www.apache.org/licenses/LICENSE-2.0 *
9+ * *
10+ * Unless required by applicable law or agreed to in writing, software *
11+ * distributed under the License is distributed on an "AS IS" BASIS, *
12+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
13+ * See the License for the specific language governing permissions and *
14+ * limitations under the License. *
15+ ***************************************************************************/
16+
17+ // Package handlers //
18+ package handlers
19+
20+ import (
21+ "context"
22+ "net/http"
23+ "net/http/httptest"
24+ "testing"
25+
26+ "github.com/optimizely/agent/pkg/middleware"
27+ "github.com/optimizely/agent/pkg/optimizely"
28+ "github.com/optimizely/agent/pkg/optimizely/optimizelytest"
29+
30+ "github.com/go-chi/chi/v5"
31+ "github.com/stretchr/testify/mock"
32+ "github.com/stretchr/testify/suite"
33+ )
34+
35+ type MockCache struct {
36+ mock.Mock
37+ }
38+
39+ func (m * MockCache ) GetClient (key string ) (* optimizely.OptlyClient , error ) {
40+ args := m .Called (key )
41+ return args .Get (0 ).(* optimizely.OptlyClient ), args .Error (1 )
42+ }
43+
44+ func (m * MockCache ) UpdateConfigs (_ string ) {
45+ }
46+
47+ func (m * MockCache ) SetUserProfileService (sdkKey , userProfileService string ) {
48+ m .Called (sdkKey , userProfileService )
49+ }
50+
51+ func (m * MockCache ) SetODPCache (sdkKey , odpCache string ) {
52+ m .Called (sdkKey , odpCache )
53+ }
54+
55+ func (m * MockCache ) ResetClient (sdkKey string ) {
56+ m .Called (sdkKey )
57+ }
58+
59+ type ResetTestSuite struct {
60+ suite.Suite
61+ oc * optimizely.OptlyClient
62+ tc * optimizelytest.TestClient
63+ mux * chi.Mux
64+ cache * MockCache
65+ }
66+
67+ func (suite * ResetTestSuite ) ClientCtx (next http.Handler ) http.Handler {
68+ return http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
69+ ctx := context .WithValue (r .Context (), middleware .OptlyClientKey , suite .oc )
70+ ctx = context .WithValue (ctx , middleware .OptlyCacheKey , suite .cache )
71+ next .ServeHTTP (w , r .WithContext (ctx ))
72+ })
73+ }
74+
75+ func (suite * ResetTestSuite ) SetupTest () {
76+ testClient := optimizelytest .NewClient ()
77+ suite .tc = testClient
78+ suite .oc = & optimizely.OptlyClient {OptimizelyClient : testClient .OptimizelyClient }
79+
80+ mockCache := new (MockCache )
81+ mockCache .On ("ResetClient" , "test-sdk-key" ).Return ()
82+ suite .cache = mockCache
83+
84+ mux := chi .NewMux ()
85+ mux .Use (suite .ClientCtx )
86+ mux .Post ("/reset" , ResetClient )
87+ suite .mux = mux
88+ }
89+
90+ func (suite * ResetTestSuite ) TestResetClient () {
91+ req := httptest .NewRequest ("POST" , "/reset" , nil )
92+ req .Header .Set ("X-Optimizely-SDK-Key" , "test-sdk-key" )
93+ recorder := httptest .NewRecorder ()
94+
95+ suite .mux .ServeHTTP (recorder , req )
96+
97+ suite .Equal (http .StatusOK , recorder .Code )
98+ suite .Contains (recorder .Header ().Get ("content-type" ), "application/json" )
99+ suite .Contains (recorder .Body .String (), `"result":true` )
100+
101+ // Verify ResetClient was called with correct SDK key
102+ suite .cache .AssertCalled (suite .T (), "ResetClient" , "test-sdk-key" )
103+ }
104+
105+ func (suite * ResetTestSuite ) TestResetClientMissingSDKKey () {
106+ req := httptest .NewRequest ("POST" , "/reset" , nil )
107+ recorder := httptest .NewRecorder ()
108+
109+ suite .mux .ServeHTTP (recorder , req )
110+
111+ suite .Equal (http .StatusBadRequest , recorder .Code )
112+ suite .Contains (recorder .Body .String (), "SDK key required for reset" )
113+ }
114+
115+ func (suite * ResetTestSuite ) TestResetClientCacheNotAvailable () {
116+ // Create a context without cache
117+ req := httptest .NewRequest ("POST" , "/reset" , nil )
118+ req .Header .Set ("X-Optimizely-SDK-Key" , "test-sdk-key" )
119+ recorder := httptest .NewRecorder ()
120+
121+ // Use middleware that doesn't include cache
122+ mux := chi .NewMux ()
123+ mux .Use (func (next http.Handler ) http.Handler {
124+ return http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
125+ ctx := context .WithValue (r .Context (), middleware .OptlyClientKey , suite .oc )
126+ // Note: no cache in context
127+ next .ServeHTTP (w , r .WithContext (ctx ))
128+ })
129+ })
130+ mux .Post ("/reset" , ResetClient )
131+
132+ mux .ServeHTTP (recorder , req )
133+
134+ suite .Equal (http .StatusInternalServerError , recorder .Code )
135+ suite .Contains (recorder .Body .String (), "cache not available" )
136+ }
137+
138+ func TestResetTestSuite (t * testing.T ) {
139+ suite .Run (t , new (ResetTestSuite ))
140+ }
0 commit comments