Skip to content

Commit 7a9c22a

Browse files
committed
test(survey): cover unset flow in acceptance tests
Add two acceptance tests to confirm the drop-omitempty fix lets users actually clear nullable fields through the provider, not just at the wire format level: * TestSurvey_ClearNumericLimits — sets responses_limit, iteration_count, iteration_frequency_days, response_sampling_interval_type, response_sampling_interval, response_sampling_limit, then drops every one of them. State after step 2 must show the attributes as unset, which only happens if PostHog actually cleared the underlying columns (MapResponseToModel maps them straight from the GET response). * TestSurvey_LinkAndUnlinkFlag — exercises the highest-stakes case: link a fresh posthog_feature_flag via linked_flag_id, then remove the attribute while keeping the flag resource around. The survey should report no linked flag. Pre-fix, this would silently keep the link because the nil pointer was omitted from the PATCH body. linked_insight_id is intentionally not covered: the response struct doesn't model linked_insight_id, so MapResponseToModel can't verify the clear from state alone. Worth a follow-up that adds the field to httpclient.Survey and a matching acceptance test.
1 parent a648ee9 commit 7a9c22a

1 file changed

Lines changed: 176 additions & 0 deletions

File tree

testacc/survey_test.go

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,3 +141,179 @@ resource "posthog_survey" "test" {
141141
}
142142
`, name)
143143
}
144+
145+
// TestSurvey_ClearNumericLimits verifies that removing the nullable numeric
146+
// attributes from config sends an explicit JSON null on PATCH, which PostHog
147+
// interprets as "clear this column", and that the resulting state reflects the
148+
// cleared values. Without the drop-omitempty fix, step 2 would still observe
149+
// the values from step 1 because the omitempty pointer would never be sent.
150+
func TestSurvey_ClearNumericLimits(t *testing.T) {
151+
skipIfNotAcceptance(t)
152+
153+
rName := acctest.RandomWithPrefix("tf-survey")
154+
155+
resource.Test(t, resource.TestCase{
156+
PreCheck: func() { testAccPreCheck(t) },
157+
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
158+
CheckDestroy: testAccCheckSurveyDestroy,
159+
Steps: []resource.TestStep{
160+
// Step 1: create with every nullable numeric field set so we have a
161+
// non-trivial baseline to clear from.
162+
{
163+
Config: testAccSurveyAllNumericLimits(rName),
164+
Check: resource.ComposeAggregateTestCheckFunc(
165+
resource.TestCheckResourceAttr(testSurveyResourceName, "schedule", "recurring"),
166+
resource.TestCheckResourceAttr(testSurveyResourceName, "responses_limit", "100"),
167+
resource.TestCheckResourceAttr(testSurveyResourceName, "iteration_count", "3"),
168+
resource.TestCheckResourceAttr(testSurveyResourceName, "iteration_frequency_days", "7"),
169+
resource.TestCheckResourceAttr(testSurveyResourceName, "response_sampling_interval_type", "week"),
170+
resource.TestCheckResourceAttr(testSurveyResourceName, "response_sampling_interval", "2"),
171+
resource.TestCheckResourceAttr(testSurveyResourceName, "response_sampling_limit", "50"),
172+
),
173+
},
174+
// Step 2: drop every nullable numeric field. State must show them as
175+
// unset, which only happens if PostHog actually cleared the columns —
176+
// MapResponseToModel reads them straight from the GET response.
177+
{
178+
Config: testAccSurveyNoNumericLimits(rName),
179+
Check: resource.ComposeAggregateTestCheckFunc(
180+
resource.TestCheckNoResourceAttr(testSurveyResourceName, "responses_limit"),
181+
resource.TestCheckNoResourceAttr(testSurveyResourceName, "iteration_count"),
182+
resource.TestCheckNoResourceAttr(testSurveyResourceName, "iteration_frequency_days"),
183+
resource.TestCheckNoResourceAttr(testSurveyResourceName, "response_sampling_interval"),
184+
resource.TestCheckNoResourceAttr(testSurveyResourceName, "response_sampling_limit"),
185+
),
186+
},
187+
},
188+
})
189+
}
190+
191+
// TestSurvey_LinkAndUnlinkFlag is the most user-visible drop-omitempty case:
192+
// linking a feature flag, then removing the linked_flag_id and confirming the
193+
// survey is actually unlinked server-side (the API response no longer
194+
// includes a linked_flag, so int64ValueFromMapOrNull surfaces null).
195+
func TestSurvey_LinkAndUnlinkFlag(t *testing.T) {
196+
skipIfNotAcceptance(t)
197+
198+
rName := acctest.RandomWithPrefix("tf-survey")
199+
200+
resource.Test(t, resource.TestCase{
201+
PreCheck: func() { testAccPreCheck(t) },
202+
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
203+
CheckDestroy: testAccCheckSurveyDestroy,
204+
Steps: []resource.TestStep{
205+
// Step 1: survey linked to a fresh feature flag.
206+
{
207+
Config: testAccSurveyWithLinkedFlag(rName),
208+
Check: resource.ComposeAggregateTestCheckFunc(
209+
resource.TestCheckResourceAttrPair(
210+
testSurveyResourceName, "linked_flag_id",
211+
"posthog_feature_flag.test", "id",
212+
),
213+
),
214+
},
215+
// Step 2: remove linked_flag_id from the survey while keeping the
216+
// flag resource around. The survey should report no linked flag.
217+
{
218+
Config: testAccSurveyWithoutLinkedFlag(rName),
219+
Check: resource.ComposeAggregateTestCheckFunc(
220+
resource.TestCheckNoResourceAttr(testSurveyResourceName, "linked_flag_id"),
221+
),
222+
},
223+
},
224+
})
225+
}
226+
227+
func testAccSurveyAllNumericLimits(name string) string {
228+
return fmt.Sprintf(`
229+
provider "posthog" {}
230+
231+
resource "posthog_survey" "test" {
232+
name = %q
233+
type = "popover"
234+
schedule = "recurring"
235+
responses_limit = 100
236+
iteration_count = 3
237+
iteration_frequency_days = 7
238+
response_sampling_interval_type = "week"
239+
response_sampling_interval = 2
240+
response_sampling_limit = 50
241+
242+
questions_json = jsonencode([
243+
{
244+
type = "open"
245+
question = "How satisfied are you?"
246+
}
247+
])
248+
}
249+
`, name)
250+
}
251+
252+
func testAccSurveyNoNumericLimits(name string) string {
253+
return fmt.Sprintf(`
254+
provider "posthog" {}
255+
256+
resource "posthog_survey" "test" {
257+
name = %q
258+
type = "popover"
259+
260+
questions_json = jsonencode([
261+
{
262+
type = "open"
263+
question = "How satisfied are you?"
264+
}
265+
])
266+
}
267+
`, name)
268+
}
269+
270+
func testAccSurveyWithLinkedFlag(name string) string {
271+
return fmt.Sprintf(`
272+
provider "posthog" {}
273+
274+
resource "posthog_feature_flag" "test" {
275+
key = %[1]q
276+
name = "Test flag for survey link"
277+
active = true
278+
rollout_percentage = 100
279+
}
280+
281+
resource "posthog_survey" "test" {
282+
name = %[1]q
283+
type = "popover"
284+
linked_flag_id = posthog_feature_flag.test.id
285+
286+
questions_json = jsonencode([
287+
{
288+
type = "open"
289+
question = "How satisfied are you?"
290+
}
291+
])
292+
}
293+
`, name)
294+
}
295+
296+
func testAccSurveyWithoutLinkedFlag(name string) string {
297+
return fmt.Sprintf(`
298+
provider "posthog" {}
299+
300+
resource "posthog_feature_flag" "test" {
301+
key = %[1]q
302+
name = "Test flag for survey link"
303+
active = true
304+
rollout_percentage = 100
305+
}
306+
307+
resource "posthog_survey" "test" {
308+
name = %[1]q
309+
type = "popover"
310+
311+
questions_json = jsonencode([
312+
{
313+
type = "open"
314+
question = "How satisfied are you?"
315+
}
316+
])
317+
}
318+
`, name)
319+
}

0 commit comments

Comments
 (0)