Skip to content

Commit a17b265

Browse files
grouvillegsnaiper
authored andcommitted
test: dedup test framework (dagger#157)
* refactor: introduce globalConfigPath for cleaner test isolation The previous OpenWithBasePath approach exposed test implementation details in the public API. This change uses a function variable pattern to allow tests to override the config path without polluting the API. Production code remains unaware of test-specific concerns while tests get the isolation they need. Trade-off: SetTestConfigPath() modifies global state, so tests using it cannot run in parallel. Signed-off-by: Guillaume de Rouville <guillaume@dagger.io> * test: remove t.Parallel() calls to support SetTestConfigPath SetTestConfigPath modifies global state, making it incompatible with parallel test execution. Remove all t.Parallel() calls from integration tests to ensure tests run sequentially and avoid race conditions. Signed-off-by: Guillaume de Rouville <guillaume@dagger.io> * refactor: extract WriteEnvironmentFile from MCP handler Extract the core logic from environment_file_write handler into a public function that can be used by both the MCP handler and test helpers. This eliminates duplication between the handler and test helpers while maintaining the same behavior. The handler now acts as a thin wrapper that handles MCP-specific concerns (parameter extraction, error formatting) while the business logic lives in the extracted function. Signed-off-by: Guillaume de Rouville <guillaume@dagger.io> * refactor: extract DeleteEnvironmentFile from MCP handler Extract the core logic from environment_file_delete handler into a public function. This follows the same pattern as WriteEnvironmentFile, allowing both the MCP handler and test helpers to use the same implementation. The handler preserves the original error message for compatibility. Signed-off-by: Guillaume de Rouville <guillaume@dagger.io> * refactor: extract ReadEnvironmentFile from MCP handler Extract the core logic from environment_file_read handler. This is a read-only operation that doesn't update the repository, making it simpler than the write operations. The handler now uses err.Error() for the error message to preserve the original behavior where different errors could occur. Signed-off-by: Guillaume de Rouville <guillaume@dagger.io> * refactor: extract RunEnvironmentCommand from MCP handler Extract the core logic from environment_run_cmd handler. This handles both foreground and background command execution, including the repository update that must happen even if the command fails. The function returns 'any' to accommodate both string output (foreground) and endpoint mappings (background). The handler formats the appropriate response based on the command type. Signed-off-by: Guillaume de Rouville <guillaume@dagger.io> * refactor: extract CreateEnvironment from MCP handler Extract the core logic from environment_create handler. This simplifies the handler to focus on MCP-specific concerns while the business logic lives in the extracted function. The handler preserves the original 'failed to create environment' error message for compatibility. Signed-off-by: Guillaume de Rouville <guillaume@dagger.io> * refactor: extract UpdateEnvironment from MCP handler Extract the core logic from environment_update handler. This handles updating environment configuration including title, instructions, base image, setup commands, environment variables, and secrets. The handler preserves the original 'unable to update the environment' error message and the detailed success response format. Signed-off-by: Guillaume de Rouville <guillaume@dagger.io> * refactor: extract ListEnvironmentFiles from MCP handler Extract the core logic from environment_file_list handler. This is a read-only operation that lists directory contents without modifying the environment. The handler preserves the original 'failed to list directory' error message for compatibility. Signed-off-by: Guillaume de Rouville <guillaume@dagger.io> * refactor: extract GetEnvironmentFromSource from MCP handler Extract the core logic from environment_open handler. This is a simple operation that opens an existing environment from a source repository. The handler preserves the original 'unable to open the environment' error message for compatibility. Signed-off-by: Guillaume de Rouville <guillaume@dagger.io> * refactor: extract AddEnvironmentService from MCP handler Extract the core logic from environment_add_service handler. This handles adding services (like databases, caches) to an environment including their configuration, ports, environment variables, and secrets. The handler preserves the original 'failed to update env' error message that was returned when either adding the service or updating the repository failed. Signed-off-by: Guillaume de Rouville <guillaume@dagger.io> * fix: CreateEnvironment returns repo to enable dirty check The refactored CreateEnvironment function wasn't returning the repository, preventing the handler from checking for uncommitted changes. Return both repo and environment from CreateEnvironment to maintain the same behavior as the original handler while keeping the extraction clean. Signed-off-by: Guillaume de Rouville <guillaume@dagger.io> * chore: apply go fmt Run go fmt to fix formatting issues: - Remove trailing whitespace - Remove extra blank lines - Ensure consistent formatting Signed-off-by: Guillaume de Rouville <guillaume@dagger.io> * fix: remove t.Parallel() from tests using SetTestConfigPath SetTestConfigPath modifies a global variable, making it unsafe for parallel test execution. Tests were racing and causing CI failures. Added warning comment to WithRepository to prevent future issues. Signed-off-by: Guillaume de Rouville <guillaume@dagger.io> * feat: add lint check for t.Parallel() with WithRepository Add a simple grep-based check to prevent using t.Parallel() in test files that also use WithRepository. This prevents race conditions caused by WithRepository's use of SetTestConfigPath global variable. The check is file-level (not function-level) for simplicity, which may cause false positives but ensures all real issues are caught. Signed-off-by: Guillaume de Rouville <guillaume@dagger.io> * chore: keep rely on the proper daggerClienKey Signed-off-by: Guillaume de Rouville <guillaume@dagger.io> --------- Signed-off-by: Guillaume de Rouville <guillaume@dagger.io>
1 parent facdf21 commit a17b265

File tree

7 files changed

+471
-155
lines changed

7 files changed

+471
-155
lines changed

.dagger/main.go

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,10 +87,58 @@ func (m *ContainerUse) Test(ctx context.Context,
8787
Stdout(ctx)
8888
}
8989

90-
// Test runs the linter
90+
// Lint runs the linter and custom checks
9191
func (m *ContainerUse) Lint(ctx context.Context) error {
92-
return dag.
92+
// Run golangci-lint
93+
err := dag.
9394
Golangci().
9495
Lint(m.Source, dagger.GolangciLintOpts{}).
9596
Assert(ctx)
97+
if err != nil {
98+
return err
99+
}
100+
101+
// Check for t.Parallel() in tests using WithRepository
102+
// This is a simple grep-based check that prevents race conditions
103+
// WithRepository uses SetTestConfigPath which modifies global state
104+
checkScript := `#!/bin/bash
105+
set -e
106+
107+
echo "Checking for t.Parallel() in tests using WithRepository..."
108+
109+
# Find test files that use WithRepository
110+
files_with_repo=$(grep -l "WithRepository" environment/integration/*_test.go 2>/dev/null || true)
111+
112+
if [ -z "$files_with_repo" ]; then
113+
echo "No test files found using WithRepository"
114+
exit 0
115+
fi
116+
117+
# Check each file for t.Parallel()
118+
found_issues=false
119+
for file in $files_with_repo; do
120+
if grep -q "t\.Parallel()" "$file"; then
121+
echo "ERROR: $file uses both WithRepository and t.Parallel()"
122+
echo " WithRepository modifies global state and is not safe for parallel execution"
123+
found_issues=true
124+
fi
125+
done
126+
127+
if [ "$found_issues" = true ]; then
128+
echo ""
129+
echo "Tests using WithRepository must not call t.Parallel() as it causes race conditions."
130+
exit 1
131+
fi
132+
133+
echo "✓ No parallel test issues found"
134+
`
135+
136+
_, err = dag.Go(m.Source).
137+
Base().
138+
WithMountedDirectory("/src", m.Source).
139+
WithWorkdir("/src").
140+
WithExec([]string{"bash", "-c", checkScript}).
141+
Sync(ctx)
142+
143+
return err
96144
}

environment/integration/helpers.go

Lines changed: 51 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010

1111
"dagger.io/dagger"
1212
"github.com/dagger/container-use/environment"
13+
"github.com/dagger/container-use/mcpserver"
1314
"github.com/dagger/container-use/repository"
1415
"github.com/stretchr/testify/assert"
1516
"github.com/stretchr/testify/require"
@@ -35,6 +36,10 @@ func init() {
3536
}
3637

3738
// WithRepository runs a test function with an isolated repository and UserActions
39+
//
40+
// WARNING: Tests using WithRepository MUST NOT call t.Parallel() because
41+
// SetTestConfigPath modifies a global variable. Parallel tests will race
42+
// and cause unpredictable failures.
3843
func WithRepository(t *testing.T, name string, setup RepositorySetup, fn func(t *testing.T, repo *repository.Repository, user *UserActions)) {
3944
// Initialize Dagger (needed for environment operations)
4045
initializeDaggerOnce(t)
@@ -48,6 +53,10 @@ func WithRepository(t *testing.T, name string, setup RepositorySetup, fn func(t
4853
configDir, err := os.MkdirTemp("", "cu-test-config-"+name+"-*")
4954
require.NoError(t, err, "Failed to create config dir")
5055

56+
// Override the global config path for this test
57+
cleanup := repository.SetTestConfigPath(configDir)
58+
t.Cleanup(cleanup)
59+
5160
// Initialize git repo
5261
cmds := [][]string{
5362
{"init"},
@@ -66,19 +75,19 @@ func WithRepository(t *testing.T, name string, setup RepositorySetup, fn func(t
6675
setup(t, repoDir)
6776
}
6877

69-
// Open repository with isolated base path
70-
repo, err := repository.OpenWithBasePath(ctx, repoDir, configDir)
78+
// Open repository - it will use the isolated base path from context
79+
repo, err := repository.Open(ctx, repoDir)
7180
require.NoError(t, err, "Failed to open repository")
7281

7382
// Create UserActions with extended capabilities
74-
user := NewUserActions(t, repo, testDaggerClient).WithDirectAccess(repoDir, configDir)
83+
user := NewUserActions(ctx, t, repo, testDaggerClient).WithDirectAccess(repoDir, configDir)
7584

7685
// Cleanup
7786
t.Cleanup(func() {
7887
// Clean up any environments created during the test
79-
envs, _ := repo.List(context.Background())
88+
envs, _ := repo.List(ctx)
8089
for _, env := range envs {
81-
repo.Delete(context.Background(), env.ID)
90+
repo.Delete(ctx, env.ID)
8291
}
8392

8493
// Remove directories
@@ -184,10 +193,10 @@ type UserActions struct {
184193
configDir string // Container-use config directory
185194
}
186195

187-
func NewUserActions(t *testing.T, repo *repository.Repository, dag *dagger.Client) *UserActions {
196+
func NewUserActions(ctx context.Context, t *testing.T, repo *repository.Repository, dag *dagger.Client) *UserActions {
188197
return &UserActions{
189198
t: t,
190-
ctx: context.Background(),
199+
ctx: ctx,
191200
repo: repo,
192201
dag: dag,
193202
}
@@ -202,71 +211,45 @@ func (u *UserActions) WithDirectAccess(repoDir, configDir string) *UserActions {
202211

203212
// FileWrite mirrors environment_file_write MCP tool behavior
204213
func (u *UserActions) FileWrite(envID, targetFile, contents, explanation string) {
205-
env, err := u.repo.Get(u.ctx, u.dag, envID)
206-
require.NoError(u.t, err, "Failed to get environment %s", envID)
207-
208-
err = env.FileWrite(u.ctx, explanation, targetFile, contents)
214+
err := mcpserver.WriteEnvironmentFile(u.ctx, u.dag, u.repoDir, envID, targetFile, contents, explanation)
209215
require.NoError(u.t, err, "FileWrite should succeed")
210-
211-
err = u.repo.Update(u.ctx, env, explanation)
212-
require.NoError(u.t, err, "repo.Update after FileWrite should succeed")
213216
}
214217

215218
// RunCommand mirrors environment_run_cmd MCP tool behavior
216219
func (u *UserActions) RunCommand(envID, command, explanation string) string {
217-
env, err := u.repo.Get(u.ctx, u.dag, envID)
218-
require.NoError(u.t, err, "Failed to get environment %s", envID)
219-
220-
output, err := env.Run(u.ctx, command, "/bin/sh", false)
220+
result, err := mcpserver.RunEnvironmentCommand(u.ctx, u.dag, u.repoDir, envID, command, "/bin/sh", explanation, false, false, nil)
221221
require.NoError(u.t, err, "Run command should succeed")
222+
require.NotNil(u.t, result, "Run command should return a result")
222223

223-
err = u.repo.Update(u.ctx, env, explanation)
224-
require.NoError(u.t, err, "repo.Update after Run should succeed")
225-
224+
// For non-background commands, result is a string
225+
output, ok := result.(string)
226+
require.True(u.t, ok, "Run command should return string output")
226227
return output
227228
}
228229

229230
// CreateEnvironment mirrors environment_create MCP tool behavior
230231
func (u *UserActions) CreateEnvironment(title, explanation string) *environment.Environment {
231-
env, err := u.repo.Create(u.ctx, u.dag, title, explanation)
232+
_, env, err := mcpserver.CreateEnvironment(u.ctx, u.dag, u.repoDir, title, explanation)
232233
require.NoError(u.t, err, "Create environment should succeed")
234+
require.NotNil(u.t, env, "Create environment should return an environment")
233235
return env
234236
}
235237

236238
// UpdateEnvironment mirrors environment_update MCP tool behavior
237239
func (u *UserActions) UpdateEnvironment(envID, title, explanation string, config *environment.EnvironmentConfig) {
238-
env, err := u.repo.Get(u.ctx, u.dag, envID)
239-
require.NoError(u.t, err, "Failed to get environment %s", envID)
240-
241-
if title != "" {
242-
env.State.Title = title
243-
}
244-
245-
err = env.UpdateConfig(u.ctx, explanation, config)
246-
require.NoError(u.t, err, "UpdateConfig should succeed")
247-
248-
err = u.repo.Update(u.ctx, env, explanation)
249-
require.NoError(u.t, err, "repo.Update after UpdateConfig should succeed")
240+
_, err := mcpserver.UpdateEnvironment(u.ctx, u.dag, u.repoDir, envID, title, config.Instructions, config.BaseImage, explanation, config.SetupCommands, config.Env, config.Secrets)
241+
require.NoError(u.t, err, "UpdateEnvironment should succeed")
250242
}
251243

252244
// FileDelete mirrors environment_file_delete MCP tool behavior
253245
func (u *UserActions) FileDelete(envID, targetFile, explanation string) {
254-
env, err := u.repo.Get(u.ctx, u.dag, envID)
255-
require.NoError(u.t, err, "Failed to get environment %s", envID)
256-
257-
err = env.FileDelete(u.ctx, explanation, targetFile)
246+
err := mcpserver.DeleteEnvironmentFile(u.ctx, u.dag, u.repoDir, envID, targetFile, explanation)
258247
require.NoError(u.t, err, "FileDelete should succeed")
259-
260-
err = u.repo.Update(u.ctx, env, explanation)
261-
require.NoError(u.t, err, "repo.Update after FileDelete should succeed")
262248
}
263249

264250
// FileRead mirrors environment_file_read MCP tool behavior (read-only, no update)
265251
func (u *UserActions) FileRead(envID, targetFile string) string {
266-
env, err := u.repo.Get(u.ctx, u.dag, envID)
267-
require.NoError(u.t, err, "Failed to get environment %s", envID)
268-
269-
content, err := env.FileRead(u.ctx, targetFile, true, 0, 0)
252+
content, err := mcpserver.ReadEnvironmentFile(u.ctx, u.dag, u.repoDir, envID, targetFile, true, 0, 0)
270253
require.NoError(u.t, err, "FileRead should succeed")
271254
return content
272255
}
@@ -280,6 +263,13 @@ func (u *UserActions) FileReadExpectError(envID, targetFile string) {
280263
assert.Error(u.t, err, "FileRead should fail for %s", targetFile)
281264
}
282265

266+
// FileList mirrors environment_file_list MCP tool behavior
267+
func (u *UserActions) FileList(envID, path string) string {
268+
content, err := mcpserver.ListEnvironmentFiles(u.ctx, u.dag, u.repoDir, envID, path)
269+
require.NoError(u.t, err, "FileList should succeed")
270+
return content
271+
}
272+
283273
// GetEnvironment retrieves an environment by ID - mirrors how MCP tools work
284274
// Each MCP tool call starts fresh by getting the environment from the repository
285275
func (u *UserActions) GetEnvironment(envID string) *environment.Environment {
@@ -288,6 +278,22 @@ func (u *UserActions) GetEnvironment(envID string) *environment.Environment {
288278
return env
289279
}
290280

281+
// OpenEnvironment mirrors environment_open MCP tool behavior
282+
func (u *UserActions) OpenEnvironment(envID string) *environment.Environment {
283+
env, err := mcpserver.GetEnvironmentFromSource(u.ctx, u.dag, u.repoDir, envID)
284+
require.NoError(u.t, err, "OpenEnvironment should succeed")
285+
require.NotNil(u.t, env, "OpenEnvironment should return an environment")
286+
return env
287+
}
288+
289+
// AddService mirrors environment_add_service MCP tool behavior
290+
func (u *UserActions) AddService(envID, name, image, command, explanation string, ports []int, envs []string, secrets []string) *environment.Service {
291+
service, err := mcpserver.AddEnvironmentService(u.ctx, u.dag, u.repoDir, envID, name, image, command, explanation, ports, envs, secrets)
292+
require.NoError(u.t, err, "AddService should succeed")
293+
require.NotNil(u.t, service, "AddService should return a service")
294+
return service
295+
}
296+
291297
// --- Direct manipulation methods for edge case testing ---
292298

293299
// WriteSourceFile writes directly to the source repository

environment/integration/integration_test.go

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import (
1818

1919
// TestGitAuditTrail verifies that all operations are tracked in git
2020
func TestGitAuditTrail(t *testing.T) {
21-
t.Parallel()
2221
if testing.Short() {
2322
t.Skip("Skipping integration test")
2423
}
@@ -61,7 +60,6 @@ func TestGitAuditTrail(t *testing.T) {
6160

6261
// TestEnvironmentIsolation verifies that changes in one environment don't affect others
6362
func TestEnvironmentIsolation(t *testing.T) {
64-
t.Parallel()
6563
if testing.Short() {
6664
t.Skip("Skipping integration test")
6765
}
@@ -106,7 +104,6 @@ func TestEnvironmentIsolation(t *testing.T) {
106104

107105
// TestSystemHandlesProblematicFiles verifies edge cases don't break the system
108106
func TestSystemHandlesProblematicFiles(t *testing.T) {
109-
t.Parallel()
110107
if testing.Short() {
111108
t.Skip("Skipping integration test")
112109
}
@@ -183,7 +180,6 @@ func TestSystemHandlesProblematicFiles(t *testing.T) {
183180

184181
// Large project performance ensures the system scales to real-world codebases
185182
func TestLargeProjectPerformance(t *testing.T) {
186-
t.Parallel()
187183
if testing.Short() {
188184
t.Skip("Skipping performance test")
189185
}
@@ -216,7 +212,6 @@ func TestLargeProjectPerformance(t *testing.T) {
216212

217213
// TestWorktreeUpdatesAreVisibleAfterRebuild verifies file changes persist through rebuilds
218214
func TestWorktreeUpdatesAreVisibleAfterRebuild(t *testing.T) {
219-
t.Parallel()
220215
if testing.Short() {
221216
t.Skip("Skipping integration test")
222217
}
@@ -256,7 +251,6 @@ func TestWorktreeUpdatesAreVisibleAfterRebuild(t *testing.T) {
256251

257252
// TestWeirdUserScenarios verifies edge case handling
258253
func TestWeirdUserScenarios(t *testing.T) {
259-
t.Parallel()
260254
if testing.Short() {
261255
t.Skip("Skipping integration test")
262256
}
@@ -400,7 +394,6 @@ func TestWeirdUserScenarios(t *testing.T) {
400394

401395
// TestEnvironmentConfigurationPersists verifies configuration persistence
402396
func TestEnvironmentConfigurationPersists(t *testing.T) {
403-
t.Parallel()
404397
if testing.Short() {
405398
t.Skip("Skipping integration test")
406399
}

environment/integration/merge_test.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import (
1515

1616
// TestRepositoryMerge tests merging an environment into the main branch
1717
func TestRepositoryMerge(t *testing.T) {
18-
t.Parallel()
1918
WithRepository(t, "repository-merge", SetupEmptyRepo, func(t *testing.T, repo *repository.Repository, user *UserActions) {
2019
ctx := context.Background()
2120

@@ -63,7 +62,6 @@ func TestRepositoryMerge(t *testing.T) {
6362

6463
// TestRepositoryMergeNonExistent tests merging a non-existent environment
6564
func TestRepositoryMergeNonExistent(t *testing.T) {
66-
t.Parallel()
6765
WithRepository(t, "repository-merge-nonexistent", SetupEmptyRepo, func(t *testing.T, repo *repository.Repository, user *UserActions) {
6866
ctx := context.Background()
6967

@@ -77,7 +75,6 @@ func TestRepositoryMergeNonExistent(t *testing.T) {
7775

7876
// TestRepositoryMergeWithConflicts tests merge behavior when there are conflicts
7977
func TestRepositoryMergeWithConflicts(t *testing.T) {
80-
t.Parallel()
8178
WithRepository(t, "repository-merge-conflicts", SetupEmptyRepo, func(t *testing.T, repo *repository.Repository, user *UserActions) {
8279
ctx := context.Background()
8380

@@ -108,7 +105,6 @@ func TestRepositoryMergeWithConflicts(t *testing.T) {
108105
// TestRepositoryMergeCompleted tests merging the same environment multiple times
109106
// This should result in fast-forward merges since the main branch doesn't diverge
110107
func TestRepositoryMergeCompleted(t *testing.T) {
111-
t.Parallel()
112108
WithRepository(t, "repository-merge-completed", SetupEmptyRepo, func(t *testing.T, repo *repository.Repository, user *UserActions) {
113109
ctx := context.Background()
114110

environment/integration/repository_test.go

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import (
1414

1515
// TestRepositoryCreate tests creating a new environment
1616
func TestRepositoryCreate(t *testing.T) {
17-
t.Parallel()
1817
WithRepository(t, "repository-create", SetupEmptyRepo, func(t *testing.T, repo *repository.Repository, user *UserActions) {
1918
// Create an environment
2019
env := user.CreateEnvironment("Test Create", "Testing repository create")
@@ -34,7 +33,6 @@ func TestRepositoryCreate(t *testing.T) {
3433

3534
// TestRepositoryGet tests retrieving an existing environment
3635
func TestRepositoryGet(t *testing.T) {
37-
t.Parallel()
3836
WithRepository(t, "repository-get", SetupEmptyRepo, func(t *testing.T, repo *repository.Repository, user *UserActions) {
3937
ctx := context.Background()
4038

@@ -56,7 +54,6 @@ func TestRepositoryGet(t *testing.T) {
5654

5755
// TestRepositoryList tests listing all environments
5856
func TestRepositoryList(t *testing.T) {
59-
t.Parallel()
6057
WithRepository(t, "repository-list", SetupEmptyRepo, func(t *testing.T, repo *repository.Repository, user *UserActions) {
6158
ctx := context.Background()
6259

@@ -81,7 +78,6 @@ func TestRepositoryList(t *testing.T) {
8178

8279
// TestRepositoryDelete tests deleting an environment
8380
func TestRepositoryDelete(t *testing.T) {
84-
t.Parallel()
8581
WithRepository(t, "repository-delete", SetupEmptyRepo, func(t *testing.T, repo *repository.Repository, user *UserActions) {
8682
ctx := context.Background()
8783

@@ -106,7 +102,6 @@ func TestRepositoryDelete(t *testing.T) {
106102

107103
// TestRepositoryCheckout tests checking out an environment branch
108104
func TestRepositoryCheckout(t *testing.T) {
109-
t.Parallel()
110105
WithRepository(t, "repository-checkout", SetupEmptyRepo, func(t *testing.T, repo *repository.Repository, user *UserActions) {
111106
ctx := context.Background()
112107

@@ -131,7 +126,6 @@ func TestRepositoryCheckout(t *testing.T) {
131126

132127
// TestRepositoryLog tests retrieving commit history for an environment
133128
func TestRepositoryLog(t *testing.T) {
134-
t.Parallel()
135129
WithRepository(t, "repository-log", SetupEmptyRepo, func(t *testing.T, repo *repository.Repository, user *UserActions) {
136130
ctx := context.Background()
137131

@@ -170,7 +164,6 @@ func TestRepositoryLog(t *testing.T) {
170164

171165
// TestRepositoryDiff tests retrieving changes between commits
172166
func TestRepositoryDiff(t *testing.T) {
173-
t.Parallel()
174167
WithRepository(t, "repository-diff", SetupEmptyRepo, func(t *testing.T, repo *repository.Repository, user *UserActions) {
175168
ctx := context.Background()
176169

0 commit comments

Comments
 (0)