Coverage for apps / ai / fixtures.py: 0%

49 statements  

« prev     ^ index     » next       coverage.py v7.13.4, created at 2026-02-14 19:13 +0000

1"""Realistic AI response fixtures for testing. 

2 

3These fixtures represent actual AI responses including edge cases like: 

4- Missing optional fields 

5- Null values where allowed 

6- Various string formats 

7- Edge case data values 

8""" 

9 

10# Valid responses for each prompt type 

11VALID_RECIPE_REMIX = { 

12 "title": "Vegan Thai Peanut Noodles", 

13 "description": "A plant-based twist on classic pad thai with creamy peanut sauce", 

14 "ingredients": [ 

15 "8 oz rice noodles", 

16 "1/4 cup creamy peanut butter", 

17 "3 tbsp soy sauce", 

18 "2 tbsp rice vinegar", 

19 "1 tbsp maple syrup", 

20 "1 tbsp sesame oil", 

21 "2 cloves garlic, minced", 

22 "1 block extra-firm tofu, pressed and cubed", 

23 "2 cups shredded cabbage", 

24 "1 red bell pepper, sliced", 

25 "1/2 cup green onions, chopped", 

26 "1/4 cup crushed peanuts", 

27 "Fresh cilantro for garnish", 

28 ], 

29 "instructions": [ 

30 "Cook rice noodles according to package directions, drain and set aside.", 

31 "In a small bowl, whisk together peanut butter, soy sauce, rice vinegar, maple syrup, and 2 tbsp warm water.", 

32 "Heat sesame oil in a large wok or skillet over medium-high heat.", 

33 "Add tofu cubes and cook until golden brown on all sides, about 5-7 minutes.", 

34 "Add garlic and cook for 30 seconds until fragrant.", 

35 "Add cabbage and bell pepper, stir-fry for 3-4 minutes.", 

36 "Add cooked noodles and peanut sauce, toss to combine.", 

37 "Serve topped with green onions, crushed peanuts, and cilantro.", 

38 ], 

39 "prep_time": "15 minutes", 

40 "cook_time": "20 minutes", 

41 "total_time": "35 minutes", 

42 "yields": "4 servings", 

43} 

44 

45VALID_RECIPE_REMIX_MINIMAL = { 

46 "title": "Simple Remix", 

47 "description": "A simple recipe variation", 

48 "ingredients": ["ingredient 1", "ingredient 2"], 

49 "instructions": ["Step 1", "Step 2"], 

50} 

51 

52VALID_SERVING_ADJUSTMENT = { 

53 "ingredients": [ 

54 "2 cups all-purpose flour", 

55 "1 cup granulated sugar", 

56 "3/4 cup unsalted butter, softened", 

57 "4 large eggs", 

58 "1 cup whole milk", 

59 "2 tsp vanilla extract", 

60 "2 tsp baking powder", 

61 "1/2 tsp salt", 

62 ], 

63 "instructions": [ 

64 "Preheat oven to 350°F (175°C). Grease and flour two 9-inch round cake pans.", 

65 "In a large bowl, cream together butter and sugar until light and fluffy.", 

66 "Beat in eggs one at a time, then stir in vanilla.", 

67 "Combine flour, baking powder, and salt; gradually blend into the creamed mixture.", 

68 "Stir in milk until batter is smooth.", 

69 "Pour batter into prepared pans.", 

70 "Bake for 30-35 minutes or until a toothpick inserted comes out clean.", 

71 ], 

72 "notes": [ 

73 "Butter should be room temperature for best results", 

74 "For even layers, use a kitchen scale to divide batter equally", 

75 ], 

76 "prep_time": "20 minutes", 

77 "cook_time": "35 minutes", 

78 "total_time": "55 minutes", 

79} 

80 

81VALID_SERVING_ADJUSTMENT_MINIMAL = { 

82 "ingredients": ["1 cup flour", "1/2 cup sugar"], 

83} 

84 

85VALID_SERVING_ADJUSTMENT_WITH_NULLS = { 

86 "ingredients": ["2 cups rice", "1 can coconut milk", "1 tbsp curry paste"], 

87 "notes": ["Best served fresh"], 

88 "prep_time": None, 

89 "cook_time": "25 minutes", 

90 "total_time": None, 

91} 

92 

93VALID_TIPS_GENERATION = [ 

94 "Let the dough rest for at least 30 minutes before rolling for a more tender crust.", 

95 "Brush the crust with egg wash for a golden, shiny finish.", 

96 "Blind bake the crust with pie weights to prevent shrinking and bubbling.", 

97 "Allow the pie to cool completely before slicing for clean cuts.", 

98] 

99 

100VALID_TIPS_GENERATION_MAX = [ 

101 "Tip 1: Use room temperature ingredients", 

102 "Tip 2: Preheat your oven properly", 

103 "Tip 3: Measure ingredients accurately", 

104 "Tip 4: Follow the recipe order", 

105 "Tip 5: Let it rest before serving", 

106] 

107 

108VALID_TIMER_NAMING = {"label": "Simmer sauce"} 

109 

110VALID_REMIX_SUGGESTIONS = [ 

111 "Make it vegan by substituting eggs with flax eggs and dairy with oat milk", 

112 "Add a spicy kick with jalapeños and cayenne pepper", 

113 "Make it gluten-free using almond flour and gluten-free baking powder", 

114 "Create a Mediterranean version with olive oil, feta, and sun-dried tomatoes", 

115 "Make it keto-friendly by replacing sugar with erythritol and flour with almond flour", 

116 "Add extra protein with Greek yogurt and protein powder", 

117] 

118 

119VALID_DISCOVER_SUGGESTIONS = [ 

120 { 

121 "search_query": "autumn pumpkin soup", 

122 "title": "Cozy Pumpkin Soup", 

123 "description": "A warming soup perfect for fall evenings", 

124 }, 

125 { 

126 "search_query": "maple glazed roasted vegetables", 

127 "title": "Maple Roasted Root Vegetables", 

128 "description": "Sweet and savory side dish featuring seasonal roots", 

129 }, 

130 { 

131 "search_query": "apple cinnamon overnight oats", 

132 "title": "Apple Pie Overnight Oats", 

133 "description": "Grab-and-go breakfast with autumn flavors", 

134 }, 

135] 

136 

137VALID_SEARCH_RANKING = [2, 0, 4, 1, 3] 

138 

139VALID_SELECTOR_REPAIR = { 

140 "suggestions": [".recipe-title", "h1.recipe-name", "[data-recipe-title]"], 

141 "confidence": 0.85, 

142} 

143 

144VALID_SELECTOR_REPAIR_LOW_CONFIDENCE = { 

145 "suggestions": [".maybe-title"], 

146 "confidence": 0.3, 

147} 

148 

149VALID_NUTRITION_ESTIMATE = { 

150 "calories": "350 kcal", 

151 "carbohydrateContent": "45g", 

152 "proteinContent": "12g", 

153 "fatContent": "14g", 

154 "saturatedFatContent": "3g", 

155 "unsaturatedFatContent": "9g", 

156 "cholesterolContent": "25mg", 

157 "sodiumContent": "480mg", 

158 "fiberContent": "6g", 

159} 

160 

161VALID_NUTRITION_ESTIMATE_MINIMAL = { 

162 "calories": "200 kcal", 

163} 

164 

165# Edge case responses (still valid but unusual) 

166EDGE_CASE_EMPTY_ARRAYS = { 

167 "ingredients": [], 

168} 

169 

170EDGE_CASE_LONG_STRINGS = { 

171 "title": "A" * 500, 

172 "description": "B" * 1000, 

173 "ingredients": ["Very long ingredient " * 20], 

174 "instructions": ["Step " * 100], 

175} 

176 

177EDGE_CASE_SPECIAL_CHARACTERS = { 

178 "title": "Crème Brûlée with Café & Piña Colada", 

179 "description": "A dessert with ñ, ü, é, and 中文 characters", 

180 "ingredients": ["½ cup milk", "⅓ tsp vanilla", "1°C chilled cream"], 

181 "instructions": ["Heat to 180°F", 'Add "fresh" ingredients'], 

182} 

183 

184EDGE_CASE_UNICODE_FRACTIONS = { 

185 "ingredients": ["½ cup flour", "¼ tsp salt", "⅔ cup milk", "⅛ tsp pepper"], 

186} 

187 

188# Invalid responses for testing validation failures 

189INVALID_RECIPE_REMIX_MISSING_TITLE = { 

190 "description": "A recipe without a title", 

191 "ingredients": ["flour", "sugar"], 

192 "instructions": ["Mix", "Bake"], 

193} 

194 

195INVALID_RECIPE_REMIX_MISSING_INGREDIENTS = { 

196 "title": "Incomplete Recipe", 

197 "description": "Missing ingredients", 

198 "instructions": ["Step 1"], 

199} 

200 

201INVALID_RECIPE_REMIX_WRONG_TYPE_INGREDIENTS = { 

202 "title": "Bad Recipe", 

203 "description": "Ingredients should be array", 

204 "ingredients": "flour, sugar, eggs", 

205 "instructions": ["Mix all"], 

206} 

207 

208INVALID_RECIPE_REMIX_WRONG_TYPE_TITLE = { 

209 "title": 123, 

210 "description": "Title should be string", 

211 "ingredients": ["flour"], 

212 "instructions": ["mix"], 

213} 

214 

215INVALID_TIPS_TOO_FEW = ["Tip 1", "Tip 2"] 

216 

217INVALID_TIPS_TOO_MANY = [ 

218 "Tip 1", 

219 "Tip 2", 

220 "Tip 3", 

221 "Tip 4", 

222 "Tip 5", 

223 "Tip 6", # Max is 5 

224] 

225 

226INVALID_TIPS_WRONG_TYPE = {"tips": ["This should be an array, not object"]} 

227 

228INVALID_TIPS_WRONG_ITEM_TYPE = ["Tip 1", "Tip 2", 123, "Tip 4"] 

229 

230INVALID_REMIX_SUGGESTIONS_WRONG_COUNT = ["Suggestion 1", "Suggestion 2", "Suggestion 3"] 

231 

232INVALID_TIMER_NAMING_MISSING_LABEL = {"name": "Wrong field name"} 

233 

234INVALID_SEARCH_RANKING_WRONG_TYPE = [1, 2, "three", 4] 

235 

236INVALID_SELECTOR_REPAIR_MISSING_CONFIDENCE = { 

237 "suggestions": [".selector"], 

238} 

239 

240INVALID_SELECTOR_REPAIR_WRONG_CONFIDENCE_TYPE = { 

241 "suggestions": [".selector"], 

242 "confidence": "high", 

243} 

244 

245INVALID_DISCOVER_MISSING_QUERY = [ 

246 { 

247 "title": "Missing Query", 

248 "description": "No search_query field", 

249 } 

250] 

251 

252INVALID_DISCOVER_WRONG_ITEM_TYPE = ["This should be an object, not a string"] 

253 

254INVALID_NUTRITION_MISSING_CALORIES = { 

255 "proteinContent": "12g", 

256 "fatContent": "8g", 

257} 

258 

259INVALID_SERVING_ADJUSTMENT_MISSING_INGREDIENTS = { 

260 "notes": ["Some notes"], 

261 "prep_time": "10 minutes", 

262} 

263 

264INVALID_SERVING_ADJUSTMENT_WRONG_TIME_TYPE = { 

265 "ingredients": ["flour", "sugar"], 

266 "prep_time": 15, # Should be string or null 

267} 

268 

269# Malformed/hallucinated responses 

270MALFORMED_JSON_STRING = '{"title": "Incomplete' 

271 

272HALLUCINATED_EXTRA_FIELDS = { 

273 "title": "Recipe Title", 

274 "description": "A recipe", 

275 "ingredients": ["flour"], 

276 "instructions": ["mix"], 

277 "hallucinated_field": "AI added this unexpectedly", 

278 "another_fake_field": ["more hallucinated data"], 

279} 

280 

281HALLUCINATED_NUTRITION_IMPOSSIBLE = { 

282 "calories": "5000 kcal", # Unrealistic for a single serving 

283 "proteinContent": "500g", # Impossible protein content 

284 "fatContent": "-10g", # Negative value 

285} 

286 

287# Empty/null edge cases 

288EMPTY_OBJECT = {} 

289EMPTY_ARRAY = [] 

290NULL_RESPONSE = None 

291 

292# Boolean confusion (AI sometimes returns booleans instead of expected types) 

293BOOLEAN_CONFUSION = { 

294 "title": True, 

295 "description": False, 

296 "ingredients": True, 

297 "instructions": False, 

298} 

299 

300 

301def get_fixture(name: str): 

302 """Get a fixture by name. 

303 

304 Args: 

305 name: The fixture name (matches variable names above). 

306 

307 Returns: 

308 The fixture data. 

309 

310 Raises: 

311 KeyError: If fixture not found. 

312 """ 

313 fixtures = { 

314 "valid_recipe_remix": VALID_RECIPE_REMIX, 

315 "valid_recipe_remix_minimal": VALID_RECIPE_REMIX_MINIMAL, 

316 "valid_serving_adjustment": VALID_SERVING_ADJUSTMENT, 

317 "valid_serving_adjustment_minimal": VALID_SERVING_ADJUSTMENT_MINIMAL, 

318 "valid_serving_adjustment_with_nulls": VALID_SERVING_ADJUSTMENT_WITH_NULLS, 

319 "valid_tips_generation": VALID_TIPS_GENERATION, 

320 "valid_tips_generation_max": VALID_TIPS_GENERATION_MAX, 

321 "valid_timer_naming": VALID_TIMER_NAMING, 

322 "valid_remix_suggestions": VALID_REMIX_SUGGESTIONS, 

323 "valid_discover_suggestions": VALID_DISCOVER_SUGGESTIONS, 

324 "valid_search_ranking": VALID_SEARCH_RANKING, 

325 "valid_selector_repair": VALID_SELECTOR_REPAIR, 

326 "valid_selector_repair_low_confidence": VALID_SELECTOR_REPAIR_LOW_CONFIDENCE, 

327 "valid_nutrition_estimate": VALID_NUTRITION_ESTIMATE, 

328 "valid_nutrition_estimate_minimal": VALID_NUTRITION_ESTIMATE_MINIMAL, 

329 "invalid_recipe_remix_missing_title": INVALID_RECIPE_REMIX_MISSING_TITLE, 

330 "invalid_recipe_remix_missing_ingredients": INVALID_RECIPE_REMIX_MISSING_INGREDIENTS, 

331 "invalid_recipe_remix_wrong_type_ingredients": INVALID_RECIPE_REMIX_WRONG_TYPE_INGREDIENTS, 

332 "invalid_recipe_remix_wrong_type_title": INVALID_RECIPE_REMIX_WRONG_TYPE_TITLE, 

333 "invalid_tips_too_few": INVALID_TIPS_TOO_FEW, 

334 "invalid_tips_too_many": INVALID_TIPS_TOO_MANY, 

335 "invalid_tips_wrong_type": INVALID_TIPS_WRONG_TYPE, 

336 "invalid_tips_wrong_item_type": INVALID_TIPS_WRONG_ITEM_TYPE, 

337 "invalid_remix_suggestions_wrong_count": INVALID_REMIX_SUGGESTIONS_WRONG_COUNT, 

338 "invalid_timer_naming_missing_label": INVALID_TIMER_NAMING_MISSING_LABEL, 

339 "invalid_search_ranking_wrong_type": INVALID_SEARCH_RANKING_WRONG_TYPE, 

340 "invalid_selector_repair_missing_confidence": INVALID_SELECTOR_REPAIR_MISSING_CONFIDENCE, 

341 "invalid_selector_repair_wrong_confidence_type": INVALID_SELECTOR_REPAIR_WRONG_CONFIDENCE_TYPE, 

342 "invalid_discover_missing_query": INVALID_DISCOVER_MISSING_QUERY, 

343 "invalid_discover_wrong_item_type": INVALID_DISCOVER_WRONG_ITEM_TYPE, 

344 "invalid_nutrition_missing_calories": INVALID_NUTRITION_MISSING_CALORIES, 

345 "invalid_serving_adjustment_missing_ingredients": INVALID_SERVING_ADJUSTMENT_MISSING_INGREDIENTS, 

346 "invalid_serving_adjustment_wrong_time_type": INVALID_SERVING_ADJUSTMENT_WRONG_TIME_TYPE, 

347 } 

348 if name not in fixtures: 

349 raise KeyError(f"Fixture not found: {name}") 

350 return fixtures[name] 

← Back to Dashboard