Skip to content

Commit 63ca27b

Browse files
committed
chore: new test
1 parent e6ee453 commit 63ca27b

File tree

1 file changed

+240
-0
lines changed

1 file changed

+240
-0
lines changed

integration/file_deletion_test.go

Lines changed: 240 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
1+
package integration_tests
2+
3+
import (
4+
"os"
5+
"path/filepath"
6+
"testing"
7+
8+
"github.com/speakeasy-api/sdk-gen-config/workflow"
9+
"github.com/stretchr/testify/require"
10+
)
11+
12+
// TestFileDeletion_UnusedModelRemoved verifies that when a model is no longer used in the OpenAPI spec,
13+
// the generated model file is deleted on regeneration.
14+
func TestFileDeletion_UnusedModelRemoved(t *testing.T) {
15+
t.Parallel()
16+
temp := setupFileDeletionTestDir(t)
17+
18+
// Initial generation with both Pet and Owner models
19+
err := execute(t, temp, "run", "-t", "all", "--pinned", "--skip-compile", "--output", "console").Run()
20+
require.NoError(t, err, "Initial generation should succeed")
21+
22+
// Commit initial generation
23+
gitCommitAll(t, temp, "initial generation")
24+
25+
// Verify both model files exist
26+
petFile := filepath.Join(temp, "models", "components", "pet.go")
27+
ownerFile := filepath.Join(temp, "models", "components", "owner.go")
28+
29+
require.FileExists(t, petFile, "Pet model file should exist after initial generation")
30+
require.FileExists(t, ownerFile, "Owner model file should exist after initial generation")
31+
32+
t.Logf("Initial generation complete. Pet file: %s, Owner file: %s", petFile, ownerFile)
33+
34+
// List all generated files for debugging
35+
t.Log("Generated files after initial generation:")
36+
listGeneratedFiles(t, temp)
37+
38+
// Dump gen.lock after first generation
39+
genLockPath := filepath.Join(temp, ".speakeasy", "gen.lock")
40+
if content, err := os.ReadFile(genLockPath); err == nil {
41+
t.Logf("gen.lock after initial generation:\n%s", string(content))
42+
} else {
43+
t.Logf("Could not read gen.lock: %v", err)
44+
}
45+
46+
// Now update the spec to remove the Owner model usage
47+
specWithoutOwner := `openapi: 3.0.3
48+
info:
49+
title: Test API
50+
version: 1.0.0
51+
servers:
52+
- url: https://api.example.com
53+
paths:
54+
/pets:
55+
get:
56+
summary: List pets
57+
operationId: listPets
58+
responses:
59+
'200':
60+
description: OK
61+
content:
62+
application/json:
63+
schema:
64+
type: array
65+
items:
66+
$ref: '#/components/schemas/Pet'
67+
components:
68+
schemas:
69+
Pet:
70+
type: object
71+
properties:
72+
id:
73+
type: integer
74+
name:
75+
type: string
76+
`
77+
err = os.WriteFile(filepath.Join(temp, "spec.yaml"), []byte(specWithoutOwner), 0644)
78+
require.NoError(t, err)
79+
gitCommitAll(t, temp, "spec update: remove Owner model")
80+
81+
// Regenerate
82+
t.Log("Regenerating without Owner model...")
83+
err = execute(t, temp, "run", "-t", "all", "--pinned", "--skip-compile", "--output", "console").Run()
84+
require.NoError(t, err, "Regeneration should succeed")
85+
86+
// List generated files after regeneration for debugging
87+
t.Log("Generated files after regeneration:")
88+
listGeneratedFiles(t, temp)
89+
90+
// Dump gen.lock after regeneration
91+
if content, err := os.ReadFile(genLockPath); err == nil {
92+
t.Logf("gen.lock after regeneration:\n%s", string(content))
93+
} else {
94+
t.Logf("Could not read gen.lock: %v", err)
95+
}
96+
97+
// Pet model should still exist
98+
require.FileExists(t, petFile, "Pet model file should still exist after regeneration")
99+
100+
// Owner model should be DELETED since it's no longer used
101+
_, err = os.Stat(ownerFile)
102+
require.True(t, os.IsNotExist(err), "Owner model file should be deleted when no longer used in spec. Error: %v", err)
103+
}
104+
105+
// setupFileDeletionTestDir creates a test directory with an OpenAPI spec that uses two models
106+
func setupFileDeletionTestDir(t *testing.T) string {
107+
t.Helper()
108+
109+
temp := setupTestDir(t)
110+
111+
// Create an OpenAPI spec with TWO models: Pet and Owner
112+
// Both are used by the /pets endpoint
113+
specContent := `openapi: 3.0.3
114+
info:
115+
title: Test API
116+
version: 1.0.0
117+
servers:
118+
- url: https://api.example.com
119+
paths:
120+
/pets:
121+
get:
122+
summary: List pets
123+
operationId: listPets
124+
responses:
125+
'200':
126+
description: OK
127+
content:
128+
application/json:
129+
schema:
130+
type: array
131+
items:
132+
$ref: '#/components/schemas/Pet'
133+
/owners:
134+
get:
135+
summary: List owners
136+
operationId: listOwners
137+
responses:
138+
'200':
139+
description: OK
140+
content:
141+
application/json:
142+
schema:
143+
type: array
144+
items:
145+
$ref: '#/components/schemas/Owner'
146+
components:
147+
schemas:
148+
Pet:
149+
type: object
150+
properties:
151+
id:
152+
type: integer
153+
name:
154+
type: string
155+
Owner:
156+
type: object
157+
properties:
158+
id:
159+
type: integer
160+
name:
161+
type: string
162+
email:
163+
type: string
164+
`
165+
err := os.WriteFile(filepath.Join(temp, "spec.yaml"), []byte(specContent), 0644)
166+
require.NoError(t, err)
167+
168+
// Create .speakeasy directory
169+
err = os.MkdirAll(filepath.Join(temp, ".speakeasy"), 0755)
170+
require.NoError(t, err)
171+
172+
// Create workflow.yaml
173+
workflowFile := &workflow.Workflow{
174+
Version: workflow.WorkflowVersion,
175+
Sources: map[string]workflow.Source{
176+
"test-source": {
177+
Inputs: []workflow.Document{
178+
{Location: "spec.yaml"},
179+
},
180+
},
181+
},
182+
Targets: map[string]workflow.Target{
183+
"test-target": {
184+
Target: "go",
185+
Source: "test-source",
186+
},
187+
},
188+
}
189+
err = workflow.Save(temp, workflowFile)
190+
require.NoError(t, err)
191+
192+
// Create gen.yaml
193+
genYamlContent := `configVersion: 2.0.0
194+
generation:
195+
sdkClassName: SDK
196+
maintainOpenAPIOrder: true
197+
usageSnippets:
198+
optionalPropertyRendering: withExample
199+
go:
200+
version: 1.0.0
201+
packageName: testsdk
202+
`
203+
err = os.WriteFile(filepath.Join(temp, "gen.yaml"), []byte(genYamlContent), 0644)
204+
require.NoError(t, err)
205+
206+
// Create .genignore to exclude go.mod/go.sum from generation
207+
genignoreContent := `go.mod
208+
go.sum
209+
`
210+
err = os.WriteFile(filepath.Join(temp, ".genignore"), []byte(genignoreContent), 0644)
211+
require.NoError(t, err)
212+
213+
// Initialize git repo
214+
gitInit(t, temp)
215+
gitCommitAll(t, temp, "initial commit")
216+
217+
return temp
218+
}
219+
220+
// listGeneratedFiles lists all generated files for debugging purposes
221+
func listGeneratedFiles(t *testing.T, dir string) {
222+
t.Helper()
223+
err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
224+
if err != nil {
225+
return err
226+
}
227+
// Skip hidden directories
228+
if info.IsDir() && info.Name()[0] == '.' {
229+
return filepath.SkipDir
230+
}
231+
if !info.IsDir() {
232+
relPath, _ := filepath.Rel(dir, path)
233+
t.Logf(" %s", relPath)
234+
}
235+
return nil
236+
})
237+
if err != nil {
238+
t.Logf("Error walking directory: %v", err)
239+
}
240+
}

0 commit comments

Comments
 (0)