From 808c614a9a3b224e2f879140c2362bd13eff1a59 Mon Sep 17 00:00:00 2001 From: mirkoCrobu Date: Fri, 24 Oct 2025 11:38:17 +0200 Subject: [PATCH 1/4] make code example not mandatory --- internal/store/store.go | 3 + internal/store/store_test.go | 181 ++++++++++++++++++ .../arduino/arduino_cloud/brick_compose.yaml | 1 + .../docs/arduino/arduino_cloud/README.md | 1 + .../arduino/arduino_cloud/example_1.py | 1 + .../arduino/arduino_cloud/example_2.py | 1 + 6 files changed, 188 insertions(+) create mode 100644 internal/store/store_test.go create mode 100644 internal/store/testdata/compose/arduino/arduino_cloud/brick_compose.yaml create mode 100644 internal/store/testdata/docs/arduino/arduino_cloud/README.md create mode 100644 internal/store/testdata/examples/arduino/arduino_cloud/example_1.py create mode 100644 internal/store/testdata/examples/arduino/arduino_cloud/example_2.py diff --git a/internal/store/store.go b/internal/store/store.go index dbc14df3..ab16bac2 100644 --- a/internal/store/store.go +++ b/internal/store/store.go @@ -99,6 +99,9 @@ func (s *StaticStore) GetBrickCodeExamplesPathFromID(brickID string) (paths.Path targetDir := paths.New(s.codeExamplesPath, namespace, brickName) dirEntries, err := targetDir.ReadDir() if err != nil { + if errors.Is(err, os.ErrNotExist) { + return nil, nil + } return nil, fmt.Errorf("cannot read examples directory %q: %w", targetDir, err) } return dirEntries, nil diff --git a/internal/store/store_test.go b/internal/store/store_test.go new file mode 100644 index 00000000..806ac1d8 --- /dev/null +++ b/internal/store/store_test.go @@ -0,0 +1,181 @@ +package store + +import ( + "os" + "path/filepath" + "testing" + + "github.com/arduino/go-paths-helper" + "github.com/stretchr/testify/require" +) + +const validBrickID = "arduino:arduino_cloud" + +func setupTestStore() (*StaticStore, string) { + baseDir := paths.New("testdata").String() + return NewStaticStore(baseDir), baseDir +} + +func TestGetBrickReadmeFromID(t *testing.T) { + + store, baseDir := setupTestStore() + namespace, brickName, _ := parseBrickID(validBrickID) + expectedReadmePath := filepath.Join(baseDir, "docs", namespace, brickName, "README.md") + expectedContent, err := os.ReadFile(expectedReadmePath) + require.NoError(t, err, "Error Reading README file: %s", expectedReadmePath) + require.NotEmpty(t, expectedContent, "ReadME file is empty: %s", expectedReadmePath) + + testCases := []struct { + name string + brickID string + wantContent string + wantErr bool + wantErrIs error + wantErrMsg string + }{ + { + name: "Success - file found", + brickID: validBrickID, + wantContent: string(expectedContent), + wantErr: false, + }, + { + name: "Failure - file not found", + brickID: "namespace:non_existent_brick", + wantContent: "", + wantErr: true, + wantErrIs: os.ErrNotExist, + }, + { + name: "Failure - invalid ID", + brickID: "invalid-id", + wantContent: "", + wantErr: true, + wantErrMsg: "invalid ID", + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + + content, err := store.GetBrickReadmeFromID(tc.brickID) + + if tc.wantErr { + + require.Error(t, err, "should have returned an error") + + if tc.wantErrIs != nil { + + require.ErrorIs(t, err, tc.wantErrIs, "error type mismatch") + } + if tc.wantErrMsg != "" { + require.EqualError(t, err, tc.wantErrMsg, "error message mismatch") + } + } else { + require.NoError(t, err, "should not have returned an error") + } + require.Equal(t, tc.wantContent, content, "content mismatch") + }) + } +} + +func TestGetBrickComposeFilePathFromID(t *testing.T) { + + store, baseDir := setupTestStore() + + namespace, brickName, _ := parseBrickID(validBrickID) + + expectedPathString := filepath.Join(baseDir, "compose", namespace, brickName, "brick_compose.yaml") + + testCases := []struct { + name string + brickID string + wantPath string + wantErr bool + wantErrMsg string + }{ + { + name: "Success - valid ID", + brickID: validBrickID, + wantPath: expectedPathString, + wantErr: false, + }, + { + name: "Failure - invalid ID", + brickID: "invalid ID", + wantPath: "", + wantErr: true, + wantErrMsg: "invalid ID", + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + path, err := store.GetBrickComposeFilePathFromID(tc.brickID) + + if tc.wantErr { + require.Error(t, err, "function was expected to return an error") + require.Nil(t, path, "path was expected to be nil") + require.EqualError(t, err, tc.wantErrMsg, "error message mismatch") + } else { + require.NoError(t, err, "function was not expected to return an error") + require.NotNil(t, path, "path was expected to be not nil") + require.Equal(t, tc.wantPath, path.String(), "path string mismatch") + } + }) + } +} + +func TestGetBrickCodeExamplesPathFromID(t *testing.T) { + store, _ := setupTestStore() + + const expectedEntryCount = 2 + + testCases := []struct { + name string + brickID string + wantNilList bool + wantEntryCount int + wantErr bool + wantErrMsg string + }{ + { + name: "Success - directory found", + brickID: validBrickID, + wantNilList: false, + wantEntryCount: expectedEntryCount, + wantErr: false, + }, + { + name: "Success - directory not found", + brickID: "namespace:non_existent_brick", + wantNilList: true, + wantErr: false, + }, + { + name: "Failure - invalid ID", + brickID: "invalid-id", + wantNilList: true, + wantErr: true, + wantErrMsg: "invalid ID", + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + pathList, err := store.GetBrickCodeExamplesPathFromID(tc.brickID) + if tc.wantErr { + require.Error(t, err, "should have returned an error") + require.EqualError(t, err, tc.wantErrMsg, "error message mismatch") + } else { + require.NoError(t, err, "should not have returned an error") + } + + if tc.wantNilList { + require.Nil(t, pathList, "pathList should be nil") + } else { + require.NotNil(t, pathList, "pathList should not be nil") + } + require.Equal(t, tc.wantEntryCount, len(pathList), "entry count mismatch") + }) + } +} diff --git a/internal/store/testdata/compose/arduino/arduino_cloud/brick_compose.yaml b/internal/store/testdata/compose/arduino/arduino_cloud/brick_compose.yaml new file mode 100644 index 00000000..bdf08de0 --- /dev/null +++ b/internal/store/testdata/compose/arduino/arduino_cloud/brick_compose.yaml @@ -0,0 +1 @@ +test file \ No newline at end of file diff --git a/internal/store/testdata/docs/arduino/arduino_cloud/README.md b/internal/store/testdata/docs/arduino/arduino_cloud/README.md new file mode 100644 index 00000000..bdf08de0 --- /dev/null +++ b/internal/store/testdata/docs/arduino/arduino_cloud/README.md @@ -0,0 +1 @@ +test file \ No newline at end of file diff --git a/internal/store/testdata/examples/arduino/arduino_cloud/example_1.py b/internal/store/testdata/examples/arduino/arduino_cloud/example_1.py new file mode 100644 index 00000000..0edce257 --- /dev/null +++ b/internal/store/testdata/examples/arduino/arduino_cloud/example_1.py @@ -0,0 +1 @@ +# test file 1 \ No newline at end of file diff --git a/internal/store/testdata/examples/arduino/arduino_cloud/example_2.py b/internal/store/testdata/examples/arduino/arduino_cloud/example_2.py new file mode 100644 index 00000000..c85f7742 --- /dev/null +++ b/internal/store/testdata/examples/arduino/arduino_cloud/example_2.py @@ -0,0 +1 @@ +#test file 2 \ No newline at end of file From fd06714d49d5535aa688fde318370bdc1901816f Mon Sep 17 00:00:00 2001 From: mirkoCrobu Date: Fri, 24 Oct 2025 13:47:15 +0200 Subject: [PATCH 2/4] fix texdata structure --- internal/store/store_test.go | 26 +++++++------------ .../arduino/arduino_cloud/brick_compose.yaml | 0 .../docs/arduino/arduino_cloud/README.md | 0 .../arduino/arduino_cloud/example_1.py | 0 .../arduino/arduino_cloud/example_2.py | 0 5 files changed, 9 insertions(+), 17 deletions(-) rename internal/store/testdata/{ => assets/0.4.8}/compose/arduino/arduino_cloud/brick_compose.yaml (100%) rename internal/store/testdata/{ => assets/0.4.8}/docs/arduino/arduino_cloud/README.md (100%) rename internal/store/testdata/{ => assets/0.4.8}/examples/arduino/arduino_cloud/example_1.py (100%) rename internal/store/testdata/{ => assets/0.4.8}/examples/arduino/arduino_cloud/example_2.py (100%) diff --git a/internal/store/store_test.go b/internal/store/store_test.go index 806ac1d8..12f07685 100644 --- a/internal/store/store_test.go +++ b/internal/store/store_test.go @@ -7,18 +7,21 @@ import ( "github.com/arduino/go-paths-helper" "github.com/stretchr/testify/require" + + "github.com/arduino/arduino-app-cli/internal/orchestrator/config" ) const validBrickID = "arduino:arduino_cloud" -func setupTestStore() (*StaticStore, string) { - baseDir := paths.New("testdata").String() +func setupTestStore(t *testing.T) (*StaticStore, string) { + cfg, err := config.NewFromEnv() + require.NoError(t, err) + baseDir := paths.New("testdata", "assets", cfg.RunnerVersion).String() return NewStaticStore(baseDir), baseDir } func TestGetBrickReadmeFromID(t *testing.T) { - - store, baseDir := setupTestStore() + store, baseDir := setupTestStore(t) namespace, brickName, _ := parseBrickID(validBrickID) expectedReadmePath := filepath.Join(baseDir, "docs", namespace, brickName, "README.md") expectedContent, err := os.ReadFile(expectedReadmePath) @@ -57,15 +60,10 @@ func TestGetBrickReadmeFromID(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - content, err := store.GetBrickReadmeFromID(tc.brickID) - if tc.wantErr { - require.Error(t, err, "should have returned an error") - if tc.wantErrIs != nil { - require.ErrorIs(t, err, tc.wantErrIs, "error type mismatch") } if tc.wantErrMsg != "" { @@ -80,11 +78,8 @@ func TestGetBrickReadmeFromID(t *testing.T) { } func TestGetBrickComposeFilePathFromID(t *testing.T) { - - store, baseDir := setupTestStore() - + store, baseDir := setupTestStore(t) namespace, brickName, _ := parseBrickID(validBrickID) - expectedPathString := filepath.Join(baseDir, "compose", namespace, brickName, "brick_compose.yaml") testCases := []struct { @@ -112,7 +107,6 @@ func TestGetBrickComposeFilePathFromID(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { path, err := store.GetBrickComposeFilePathFromID(tc.brickID) - if tc.wantErr { require.Error(t, err, "function was expected to return an error") require.Nil(t, path, "path was expected to be nil") @@ -127,8 +121,7 @@ func TestGetBrickComposeFilePathFromID(t *testing.T) { } func TestGetBrickCodeExamplesPathFromID(t *testing.T) { - store, _ := setupTestStore() - + store, _ := setupTestStore(t) const expectedEntryCount = 2 testCases := []struct { @@ -169,7 +162,6 @@ func TestGetBrickCodeExamplesPathFromID(t *testing.T) { } else { require.NoError(t, err, "should not have returned an error") } - if tc.wantNilList { require.Nil(t, pathList, "pathList should be nil") } else { diff --git a/internal/store/testdata/compose/arduino/arduino_cloud/brick_compose.yaml b/internal/store/testdata/assets/0.4.8/compose/arduino/arduino_cloud/brick_compose.yaml similarity index 100% rename from internal/store/testdata/compose/arduino/arduino_cloud/brick_compose.yaml rename to internal/store/testdata/assets/0.4.8/compose/arduino/arduino_cloud/brick_compose.yaml diff --git a/internal/store/testdata/docs/arduino/arduino_cloud/README.md b/internal/store/testdata/assets/0.4.8/docs/arduino/arduino_cloud/README.md similarity index 100% rename from internal/store/testdata/docs/arduino/arduino_cloud/README.md rename to internal/store/testdata/assets/0.4.8/docs/arduino/arduino_cloud/README.md diff --git a/internal/store/testdata/examples/arduino/arduino_cloud/example_1.py b/internal/store/testdata/assets/0.4.8/examples/arduino/arduino_cloud/example_1.py similarity index 100% rename from internal/store/testdata/examples/arduino/arduino_cloud/example_1.py rename to internal/store/testdata/assets/0.4.8/examples/arduino/arduino_cloud/example_1.py diff --git a/internal/store/testdata/examples/arduino/arduino_cloud/example_2.py b/internal/store/testdata/assets/0.4.8/examples/arduino/arduino_cloud/example_2.py similarity index 100% rename from internal/store/testdata/examples/arduino/arduino_cloud/example_2.py rename to internal/store/testdata/assets/0.4.8/examples/arduino/arduino_cloud/example_2.py From 03ea6d128a18cbb4d8a2454cd691750bbc528eff Mon Sep 17 00:00:00 2001 From: mirkoCrobu Date: Mon, 27 Oct 2025 08:47:56 +0100 Subject: [PATCH 3/4] refactoring store_test --- internal/store/store_test.go | 27 ++++--------------- .../arduino/arduino_cloud/brick_compose.yaml | 2 +- .../docs/arduino/arduino_cloud/README.md | 2 +- 3 files changed, 7 insertions(+), 24 deletions(-) diff --git a/internal/store/store_test.go b/internal/store/store_test.go index 12f07685..fe4c4036 100644 --- a/internal/store/store_test.go +++ b/internal/store/store_test.go @@ -2,31 +2,16 @@ package store import ( "os" - "path/filepath" "testing" "github.com/arduino/go-paths-helper" "github.com/stretchr/testify/require" - - "github.com/arduino/arduino-app-cli/internal/orchestrator/config" ) const validBrickID = "arduino:arduino_cloud" -func setupTestStore(t *testing.T) (*StaticStore, string) { - cfg, err := config.NewFromEnv() - require.NoError(t, err) - baseDir := paths.New("testdata", "assets", cfg.RunnerVersion).String() - return NewStaticStore(baseDir), baseDir -} - func TestGetBrickReadmeFromID(t *testing.T) { - store, baseDir := setupTestStore(t) - namespace, brickName, _ := parseBrickID(validBrickID) - expectedReadmePath := filepath.Join(baseDir, "docs", namespace, brickName, "README.md") - expectedContent, err := os.ReadFile(expectedReadmePath) - require.NoError(t, err, "Error Reading README file: %s", expectedReadmePath) - require.NotEmpty(t, expectedContent, "ReadME file is empty: %s", expectedReadmePath) + store := NewStaticStore(paths.New("testdata", "assets", "0.4.8").String()) testCases := []struct { name string @@ -39,7 +24,7 @@ func TestGetBrickReadmeFromID(t *testing.T) { { name: "Success - file found", brickID: validBrickID, - wantContent: string(expectedContent), + wantContent: "## Readme test file", wantErr: false, }, { @@ -78,9 +63,7 @@ func TestGetBrickReadmeFromID(t *testing.T) { } func TestGetBrickComposeFilePathFromID(t *testing.T) { - store, baseDir := setupTestStore(t) - namespace, brickName, _ := parseBrickID(validBrickID) - expectedPathString := filepath.Join(baseDir, "compose", namespace, brickName, "brick_compose.yaml") + store := NewStaticStore(paths.New("testdata", "assets", "0.4.8").String()) testCases := []struct { name string @@ -92,7 +75,7 @@ func TestGetBrickComposeFilePathFromID(t *testing.T) { { name: "Success - valid ID", brickID: validBrickID, - wantPath: expectedPathString, + wantPath: "testdata/assets/0.4.8/compose/arduino/arduino_cloud/brick_compose.yaml", wantErr: false, }, { @@ -121,7 +104,7 @@ func TestGetBrickComposeFilePathFromID(t *testing.T) { } func TestGetBrickCodeExamplesPathFromID(t *testing.T) { - store, _ := setupTestStore(t) + store := NewStaticStore(paths.New("testdata", "assets", "0.4.8").String()) const expectedEntryCount = 2 testCases := []struct { diff --git a/internal/store/testdata/assets/0.4.8/compose/arduino/arduino_cloud/brick_compose.yaml b/internal/store/testdata/assets/0.4.8/compose/arduino/arduino_cloud/brick_compose.yaml index bdf08de0..f7bc1cac 100644 --- a/internal/store/testdata/assets/0.4.8/compose/arduino/arduino_cloud/brick_compose.yaml +++ b/internal/store/testdata/assets/0.4.8/compose/arduino/arduino_cloud/brick_compose.yaml @@ -1 +1 @@ -test file \ No newline at end of file +## brick compose test file \ No newline at end of file diff --git a/internal/store/testdata/assets/0.4.8/docs/arduino/arduino_cloud/README.md b/internal/store/testdata/assets/0.4.8/docs/arduino/arduino_cloud/README.md index bdf08de0..fcd326fc 100644 --- a/internal/store/testdata/assets/0.4.8/docs/arduino/arduino_cloud/README.md +++ b/internal/store/testdata/assets/0.4.8/docs/arduino/arduino_cloud/README.md @@ -1 +1 @@ -test file \ No newline at end of file +## Readme test file \ No newline at end of file From 6c1ca6385df800f31ca660e89fb09b8c2f9f5f49 Mon Sep 17 00:00:00 2001 From: mirkoCrobu Date: Mon, 27 Oct 2025 14:11:51 +0100 Subject: [PATCH 4/4] refactoring store_test --- internal/store/store_test.go | 40 ++++++++++++++---------------------- 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/internal/store/store_test.go b/internal/store/store_test.go index fe4c4036..ba1ee700 100644 --- a/internal/store/store_test.go +++ b/internal/store/store_test.go @@ -1,7 +1,6 @@ package store import ( - "os" "testing" "github.com/arduino/go-paths-helper" @@ -18,7 +17,6 @@ func TestGetBrickReadmeFromID(t *testing.T) { brickID string wantContent string wantErr bool - wantErrIs error wantErrMsg string }{ { @@ -32,7 +30,7 @@ func TestGetBrickReadmeFromID(t *testing.T) { brickID: "namespace:non_existent_brick", wantContent: "", wantErr: true, - wantErrIs: os.ErrNotExist, + wantErrMsg: "open testdata/assets/0.4.8/docs/namespace/non_existent_brick/README.md: no such file or directory", }, { name: "Failure - invalid ID", @@ -48,9 +46,6 @@ func TestGetBrickReadmeFromID(t *testing.T) { content, err := store.GetBrickReadmeFromID(tc.brickID) if tc.wantErr { require.Error(t, err, "should have returned an error") - if tc.wantErrIs != nil { - require.ErrorIs(t, err, tc.wantErrIs, "error type mismatch") - } if tc.wantErrMsg != "" { require.EqualError(t, err, tc.wantErrMsg, "error message mismatch") } @@ -105,47 +100,42 @@ func TestGetBrickComposeFilePathFromID(t *testing.T) { func TestGetBrickCodeExamplesPathFromID(t *testing.T) { store := NewStaticStore(paths.New("testdata", "assets", "0.4.8").String()) - const expectedEntryCount = 2 testCases := []struct { name string brickID string - wantNilList bool wantEntryCount int - wantErr bool - wantErrMsg string + wantErr string }{ { name: "Success - directory found", brickID: validBrickID, - wantNilList: false, - wantEntryCount: expectedEntryCount, - wantErr: false, + wantEntryCount: 2, + wantErr: "", }, { - name: "Success - directory not found", - brickID: "namespace:non_existent_brick", - wantNilList: true, - wantErr: false, + name: "Success - directory not found", + brickID: "namespace:non_existent_brick", + wantEntryCount: 0, + wantErr: "", }, { - name: "Failure - invalid ID", - brickID: "invalid-id", - wantNilList: true, - wantErr: true, - wantErrMsg: "invalid ID", + name: "Failure - invalid ID", + brickID: "invalid-id", + wantEntryCount: 0, + wantErr: "invalid ID", }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { pathList, err := store.GetBrickCodeExamplesPathFromID(tc.brickID) - if tc.wantErr { + if tc.wantErr != "" { require.Error(t, err, "should have returned an error") - require.EqualError(t, err, tc.wantErrMsg, "error message mismatch") + require.EqualError(t, err, tc.wantErr, "error message mismatch") } else { require.NoError(t, err, "should not have returned an error") } - if tc.wantNilList { + if tc.wantEntryCount == 0 { require.Nil(t, pathList, "pathList should be nil") } else { require.NotNil(t, pathList, "pathList should not be nil")