@@ -216,6 +216,16 @@ def test_trigger_update_version_webhooks__version_with_changes__triggers_flag_up
216216 flag_updated_env_body ["data" ]["previous_state" ]["feature_state_value" ]
217217 == v1_fs .get_feature_state_value ()
218218 )
219+ assert (
220+ flag_updated_env_body ["data" ]["new_state" ]["multivariate_feature_state_values" ]
221+ == []
222+ )
223+ assert (
224+ flag_updated_env_body ["data" ]["previous_state" ][
225+ "multivariate_feature_state_values"
226+ ]
227+ == []
228+ )
219229 assert flag_updated_env_body ["data" ]["changed_by" ] == staff_user .email
220230 assert "timestamp" in flag_updated_env_body ["data" ]
221231
@@ -235,6 +245,7 @@ def test_trigger_update_version_webhooks__version_with_changes__triggers_flag_up
235245 {
236246 "enabled" : v2_fs .enabled ,
237247 "value" : v2_fs .get_feature_state_value (),
248+ "multivariate_feature_state_values" : [],
238249 }
239250 ],
240251 },
@@ -284,12 +295,116 @@ def test_trigger_update_version_webhooks__version_without_changes__triggers_only
284295 {
285296 "enabled" : v2 .feature_states .first ().enabled ,
286297 "value" : v2 .feature_states .first ().get_feature_state_value (),
298+ "multivariate_feature_state_values" : [],
287299 }
288300 ],
289301 },
290302 }
291303
292304
305+ @responses .activate
306+ def test_trigger_update_version_webhooks__multivariate_feature__includes_mv_values_in_payloads (
307+ multivariate_feature : Feature ,
308+ environment_v2_versioning : Environment ,
309+ staff_user : FFAdminUser ,
310+ ) -> None :
311+ # Given
312+ v1 = EnvironmentFeatureVersion .objects .get (
313+ feature = multivariate_feature , environment = environment_v2_versioning
314+ )
315+ v1_fs = v1 .feature_states .first ()
316+
317+ # Bump one option's allocation in v2 so we count as a change and so
318+ # previous/new mv values differ.
319+ v2 = EnvironmentFeatureVersion .objects .create (
320+ environment = environment_v2_versioning , feature = multivariate_feature
321+ )
322+ v2_fs = v2 .feature_states .first ()
323+ v2_mv_values = list (
324+ v2_fs .multivariate_feature_state_values .select_related (
325+ "multivariate_feature_option"
326+ ).order_by ("multivariate_feature_option_id" )
327+ )
328+ bumped_mv_value = v2_mv_values [0 ]
329+ original_allocation = bumped_mv_value .percentage_allocation
330+ bumped_mv_value .percentage_allocation = original_allocation + 5
331+ bumped_mv_value .save ()
332+ v2 .publish (published_by = staff_user )
333+
334+ environment_webhook_url = "https://example.com/env-webhook/"
335+ Webhook .objects .create (
336+ environment = environment_v2_versioning ,
337+ url = environment_webhook_url ,
338+ enabled = True ,
339+ )
340+ responses .post (url = environment_webhook_url , status = 200 )
341+
342+ # When
343+ trigger_update_version_webhooks (str (v2 .uuid ))
344+
345+ # Then
346+ flag_updated_body = json .loads (responses .calls [0 ].request .body ) # type: ignore[union-attr]
347+ assert flag_updated_body ["event_type" ] == WebhookEventType .FLAG_UPDATED .name
348+
349+ expected_new_mv_payload = [
350+ {
351+ "id" : mv .id ,
352+ "multivariate_feature_option" : {
353+ "id" : mv .multivariate_feature_option_id ,
354+ "value" : mv .multivariate_feature_option .value ,
355+ },
356+ "percentage_allocation" : mv .percentage_allocation ,
357+ }
358+ for mv in v2_fs .multivariate_feature_state_values .select_related (
359+ "multivariate_feature_option"
360+ ).order_by ("multivariate_feature_option_id" )
361+ ]
362+ assert (
363+ sorted (
364+ flag_updated_body ["data" ]["new_state" ]["multivariate_feature_state_values" ],
365+ key = lambda mv : mv ["multivariate_feature_option" ]["id" ],
366+ )
367+ == expected_new_mv_payload
368+ )
369+
370+ expected_previous_mv_payload = [
371+ {
372+ "id" : mv .id ,
373+ "multivariate_feature_option" : {
374+ "id" : mv .multivariate_feature_option_id ,
375+ "value" : mv .multivariate_feature_option .value ,
376+ },
377+ "percentage_allocation" : mv .percentage_allocation ,
378+ }
379+ for mv in v1_fs .multivariate_feature_state_values .select_related (
380+ "multivariate_feature_option"
381+ ).order_by ("multivariate_feature_option_id" )
382+ ]
383+ assert (
384+ sorted (
385+ flag_updated_body ["data" ]["previous_state" ][
386+ "multivariate_feature_state_values"
387+ ],
388+ key = lambda mv : mv ["multivariate_feature_option" ]["id" ],
389+ )
390+ == expected_previous_mv_payload
391+ )
392+
393+ # NEW_VERSION_PUBLISHED summary event should also carry mv values.
394+ new_version_body = json .loads (responses .calls [1 ].request .body ) # type: ignore[union-attr]
395+ assert new_version_body ["event_type" ] == WebhookEventType .NEW_VERSION_PUBLISHED .name
396+ summary_mv_payload = new_version_body ["data" ]["feature_states" ][0 ][
397+ "multivariate_feature_state_values"
398+ ]
399+ assert (
400+ sorted (
401+ summary_mv_payload ,
402+ key = lambda mv : mv ["multivariate_feature_option" ]["id" ],
403+ )
404+ == expected_new_mv_payload
405+ )
406+
407+
293408def test_enable_v2_versioning__scheduled_changes_exist__converts_published_scheduled_changes (
294409 environment : Environment , staff_user : FFAdminUser , feature : Feature
295410) -> None :
0 commit comments