gosimplenpm/internal/handler/publish_test.go

716 lines
28 KiB
Go

package handler
import (
"bytes"
"fmt"
"gosimplenpm/internal/config"
"gosimplenpm/internal/serviceidos"
"gosimplenpm/internal/storage"
"io"
"net/http"
"net/http/httptest"
"net/url"
"os"
"testing"
"github.com/gorilla/mux"
"github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"
)
func TestUnitPublish(t *testing.T) {
t.Run("return `Internal Server` error if index.json cannot be retrieved", func(t *testing.T) {
jsonBody := []byte(
`{
"_id": "@ookusanya/simplepackone",
"name": "@ookusanya/simplepackone",
"description": "This is a very rough implementation of a private npm registry.",
"dist-tags": {
"latest": "1.2.0"
},
"versions": {
"1.2.0": {
"name": "@ookusanya/simplepackone",
"version": "1.2.0",
"description": "This is a very rough implementation of a private npm registry.",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"license": "MIT",
"files": null,
"readme": "# Gosimplenpm\n\nThis is a very rough implementation of a private npm registry.\n\n# Features\n\nTODO...\n\n# Enhancements\n\nTODO...\n\n# Work List\n\nTODO...",
"_id": "@ookusanya/simplepackone@1.2.0",
"_nodeVersion": "16.20.0",
"_npmVersion": "8.19.4",
"dist": {
"integrity": "sha512-coOiU+ywV/do/+HwK91mfuei9491yfQUedLWjspAjDa58RniJvQNTF/cXDp/sooVdpjgEbCqKVyLOju6C1i3pw==",
"shasum": "1adafdbe8878372c9f4b554bf30d5bfb1b7896c5",
"tarball": "http://localhost:4000/@ookusanya%2Fsimplepackone/-/@ookusanya%2Fsimplepackone-1.2.0.tgz"
},
"dependencies": {
"eslint": "^7.x",
"mocha": "^10.x",
"uuid": "^9.x"
}
}
},
"access": "",
"_attachments": {
"@ookusanya/simplepackone-1.2.0.tgz": {
"content_type": "application/octet-stream",
"data": "H4sIAAAAAAAC/+1XbWvjOBDuZ/+KwQtLCyZ10pfl+uncRGnMOnawne0VlgXVVmJtHctIcl849r/fSEmb9nof73LcXoaA0Lw9M6PMSG5pcUeX7Jg3JXvsfVcH/wD5vn9+egp/xbc0OIGDk7Nzv98/P/dRz+/7nwY+rgc7oE5pKjGUvyFJJHhZ/yNUiEaJmvVqsTx0J0wy9+hgT/8fajf9v1lxAohmx/1/ev6u//tnZ/19/++CfncA3IaumHsB7q9C3HWKNk/0WPFVWzPzrxANcz2jdc+k4qIxiv3eoOevuSVTheSt3kjWzBXldvd8q6y5a0WFAoOKDM2UNmqsqAR8dYmUQl5AI8AIQLWs4AvOyq8ufPwI7JFr6Lto+cN6o52uhNxi1rxgjbJ5TMP8ObiWYQhNwdkrWKZq3ljgb596j1bTxCyKilpm399yu46X7oX77RdkGWjnh/NT9n9KgtGU9Fbl7u//waD/7v4/Oxns+38X9AGuxLrXm3blOHnFFeCPAnb7E0jRLSuw4hVrNDVdDmKB4lbye6oZoBVItuRKy6ee43yAMaO6k0yhr2SU9HqWSZqKNoX18VZwLeQdRGj9wt1fyf9K/0fhkMQZ6elHveP+H/hng3f3f9/f9/9OyBmK9knyZaXhsDiCgfkYS+rugZZ0xWtRU0g2TwLHmTG54sq8AcyIqPBj4fYJlpI2mpUeLCRjZjbgLSqXzAMtAM2gxVeDGRq3Gt8EvFk6FAqENJraDBslFvqBSobKJVClRMFxrpRQiqLbzpwFr5mCQ10xx802Fu6RBSkZrYE36I3BswgeOD4OOo2jCQcTL4wPD5WKuitNDM/imq/4BsGY2zoo47RTmIGJ04OVKPnCrMym1Xa3NVeV55Rm5vHbTiNTGaZ9fngmj2MhQbG6Nh7w5bHOdRud1UEUpzUF1ZsSWdyHSqzeZoIlWnSyQUhW2nQFlswifmeFNl6M+kLUtXjA1BCyKbnJSF2YcY51vRX3zOayPuZGaAx1HYI5gHZ7qhuRqijGfsucdcEQF8tLX6UjDTz2TaM51r4V0uL9OU0c8PmEQJaM8+sgJRBmMEuTL+GIjMANMty7HlyH+SSZ54AaaRDnN5CMIYhv4HMYjzyH/DZLSZZBkkI4nUUhGXkQxsNoPgrjK7hEuzjJIQrxwYdO8wQM4MZVSNBu7ExJOpzgNrgMozC/8WAc5rHxOUanAcyCNA+H8yhIYTZPZ0lGEH7kxEkcxuMUUciUxHkPUREKyBfcQDYJoshCBXOMPrXxDZPZTRpeTXKYJNGIIPOSOFEYXEZkDYVJDaMgnHowCqbBFbFWCXpJwahtorueEMtCvAB/wzxMYgdrMkziPMWth1mm+YvpdZgRD4I0zExBxmmC7k050SKxTtAuJmsvptTw5kRQxeznGdnGMiJBhL4yY/xaeX8x72lPe9rTT0V/APlm4rcAGAAA",
"length": 1089
}
}
}`,
)
req := httptest.NewRequest(http.MethodPut, "/{name}", bytes.NewReader(jsonBody))
wrt := httptest.NewRecorder()
lg := &logrus.Logger{
Out: os.Stdout,
// Level: "DEBUG",
Formatter: &logrus.TextFormatter{
FullTimestamp: true,
TimestampFormat: "2009-01-02 15:15:15",
},
}
cfg := config.Config{
RepoDir: "",
}
mfs := &storage.MockFs{}
mfs.GetIndexJsonFromStoreFunc = func(packageName string, registryPath string, lg *logrus.Logger) (string, bool, error) {
return "", false, fmt.Errorf("Filesystem error")
}
vars := map[string]string{
"name": "@ookusanya%2Fsimplepackone",
}
req = mux.SetURLVars(req, vars)
Publish(lg, cfg, mfs)(wrt, req)
rs := wrt.Result()
assert.Equal(t, rs.StatusCode, http.StatusInternalServerError)
defer rs.Body.Close()
body, err := io.ReadAll(rs.Body)
if err != nil {
t.Fatal(err)
}
bytes.TrimSpace(body)
assert.Equal(t, string(body), "Filesystem error\n")
})
t.Run("return `Internal Server` error if index.json cannot be decoded", func(t *testing.T) {
jsonBody := []byte(
`{
"_id": "@ookusanya/simplepackone",
"name": "@ookusanya/simplepackone",
"description": "This is a very rough implementation of a private npm registry.",
"dist-tags": {
"latest": "1.2.0"
},
"versions": {
"1.2.0": {
"name": "@ookusanya/simplepackone",
"version": "1.2.0",
"description": "This is a very rough implementation of a private npm registry.",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"license": "MIT",
"files": null,
"readme": "# Gosimplenpm\n\nThis is a very rough implementation of a private npm registry.\n\n# Features\n\nTODO...\n\n# Enhancements\n\nTODO...\n\n# Work List\n\nTODO...",
"_id": "@ookusanya/simplepackone@1.2.0",
"_nodeVersion": "16.20.0",
"_npmVersion": "8.19.4",
"dist": {
"integrity": "sha512-coOiU+ywV/do/+HwK91mfuei9491yfQUedLWjspAjDa58RniJvQNTF/cXDp/sooVdpjgEbCqKVyLOju6C1i3pw==",
"shasum": "1adafdbe8878372c9f4b554bf30d5bfb1b7896c5",
"tarball": "http://localhost:4000/@ookusanya%2Fsimplepackone/-/@ookusanya%2Fsimplepackone-1.2.0.tgz"
},
"dependencies": {
"eslint": "^7.x",
"mocha": "^10.x",
"uuid": "^9.x"
}
}
},
"access": "",
"_attachments": {
"@ookusanya/simplepackone-1.2.0.tgz": {
"content_type": "application/octet-stream",
"data": "H4sIAAAAAAAC/+1XbWvjOBDuZ/+KwQtLCyZ10pfl+uncRGnMOnawne0VlgXVVmJtHctIcl849r/fSEmb9nof73LcXoaA0Lw9M6PMSG5pcUeX7Jg3JXvsfVcH/wD5vn9+egp/xbc0OIGDk7Nzv98/P/dRz+/7nwY+rgc7oE5pKjGUvyFJJHhZ/yNUiEaJmvVqsTx0J0wy9+hgT/8fajf9v1lxAohmx/1/ev6u//tnZ/19/++CfncA3IaumHsB7q9C3HWKNk/0WPFVWzPzrxANcz2jdc+k4qIxiv3eoOevuSVTheSt3kjWzBXldvd8q6y5a0WFAoOKDM2UNmqsqAR8dYmUQl5AI8AIQLWs4AvOyq8ufPwI7JFr6Lto+cN6o52uhNxi1rxgjbJ5TMP8ObiWYQhNwdkrWKZq3ljgb596j1bTxCyKilpm399yu46X7oX77RdkGWjnh/NT9n9KgtGU9Fbl7u//waD/7v4/Oxns+38X9AGuxLrXm3blOHnFFeCPAnb7E0jRLSuw4hVrNDVdDmKB4lbye6oZoBVItuRKy6ee43yAMaO6k0yhr2SU9HqWSZqKNoX18VZwLeQdRGj9wt1fyf9K/0fhkMQZ6elHveP+H/hng3f3f9/f9/9OyBmK9knyZaXhsDiCgfkYS+rugZZ0xWtRU0g2TwLHmTG54sq8AcyIqPBj4fYJlpI2mpUeLCRjZjbgLSqXzAMtAM2gxVeDGRq3Gt8EvFk6FAqENJraDBslFvqBSobKJVClRMFxrpRQiqLbzpwFr5mCQ10xx802Fu6RBSkZrYE36I3BswgeOD4OOo2jCQcTL4wPD5WKuitNDM/imq/4BsGY2zoo47RTmIGJ04OVKPnCrMym1Xa3NVeV55Rm5vHbTiNTGaZ9fngmj2MhQbG6Nh7w5bHOdRud1UEUpzUF1ZsSWdyHSqzeZoIlWnSyQUhW2nQFlswifmeFNl6M+kLUtXjA1BCyKbnJSF2YcY51vRX3zOayPuZGaAx1HYI5gHZ7qhuRqijGfsucdcEQF8tLX6UjDTz2TaM51r4V0uL9OU0c8PmEQJaM8+sgJRBmMEuTL+GIjMANMty7HlyH+SSZ54AaaRDnN5CMIYhv4HMYjzyH/DZLSZZBkkI4nUUhGXkQxsNoPgrjK7hEuzjJIQrxwYdO8wQM4MZVSNBu7ExJOpzgNrgMozC/8WAc5rHxOUanAcyCNA+H8yhIYTZPZ0lGEH7kxEkcxuMUUciUxHkPUREKyBfcQDYJoshCBXOMPrXxDZPZTRpeTXKYJNGIIPOSOFEYXEZkDYVJDaMgnHowCqbBFbFWCXpJwahtorueEMtCvAB/wzxMYgdrMkziPMWth1mm+YvpdZgRD4I0zExBxmmC7k050SKxTtAuJmsvptTw5kRQxeznGdnGMiJBhL4yY/xaeX8x72lPe9rTT0V/APlm4rcAGAAA",
"length": 1089
}
}
}`,
)
req := httptest.NewRequest(http.MethodPut, "/{name}", bytes.NewReader(jsonBody))
wrt := httptest.NewRecorder()
lg := &logrus.Logger{
Out: os.Stdout,
// Level: "DEBUG",
Formatter: &logrus.TextFormatter{
FullTimestamp: true,
TimestampFormat: "2009-01-02 15:15:15",
},
}
cfg := config.Config{
RepoDir: "",
}
mfs := &storage.MockFs{}
mfs.GetIndexJsonFromStoreFunc = func(packageName string, registryPath string, lg *logrus.Logger) (string, bool, error) {
return string(jsonBody), true, nil
}
mfs.ReadIndexJsonFunc = func(fPath string, res *serviceidos.IndexJson, lg *logrus.Logger) error {
return fmt.Errorf("Filesystem error")
}
vars := map[string]string{
"name": "@ookusanya%2Fsimplepackone",
}
req = mux.SetURLVars(req, vars)
Publish(lg, cfg, mfs)(wrt, req)
rs := wrt.Result()
assert.Equal(t, rs.StatusCode, http.StatusInternalServerError)
defer rs.Body.Close()
body, err := io.ReadAll(rs.Body)
if err != nil {
t.Fatal(err)
}
bytes.TrimSpace(body)
assert.Equal(t, string(body), "Filesystem error\n")
})
t.Run("return `Bad Request` error if version to publish already exists", func(t *testing.T) {
jsonBody := []byte(
`{
"_id": "@ookusanya/simplepackone",
"name": "@ookusanya/simplepackone",
"description": "This is a very rough implementation of a private npm registry.",
"dist-tags": {
"latest": "1.2.0"
},
"versions": {
"1.2.0": {
"name": "@ookusanya/simplepackone",
"version": "1.2.0",
"description": "This is a very rough implementation of a private npm registry.",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"license": "MIT",
"files": null,
"readme": "# Gosimplenpm\n\nThis is a very rough implementation of a private npm registry.\n\n# Features\n\nTODO...\n\n# Enhancements\n\nTODO...\n\n# Work List\n\nTODO...",
"_id": "@ookusanya/simplepackone@1.2.0",
"_nodeVersion": "16.20.0",
"_npmVersion": "8.19.4",
"dist": {
"integrity": "sha512-coOiU+ywV/do/+HwK91mfuei9491yfQUedLWjspAjDa58RniJvQNTF/cXDp/sooVdpjgEbCqKVyLOju6C1i3pw==",
"shasum": "1adafdbe8878372c9f4b554bf30d5bfb1b7896c5",
"tarball": "http://localhost:4000/@ookusanya%2Fsimplepackone/-/@ookusanya%2Fsimplepackone-1.2.0.tgz"
},
"dependencies": {
"eslint": "^7.x",
"mocha": "^10.x",
"uuid": "^9.x"
}
}
},
"access": "",
"_attachments": {
"@ookusanya/simplepackone-1.2.0.tgz": {
"content_type": "application/octet-stream",
"data": "H4sIAAAAAAAC/+1XbWvjOBDuZ/+KwQtLCyZ10pfl+uncRGnMOnawne0VlgXVVmJtHctIcl849r/fSEmb9nof73LcXoaA0Lw9M6PMSG5pcUeX7Jg3JXvsfVcH/wD5vn9+egp/xbc0OIGDk7Nzv98/P/dRz+/7nwY+rgc7oE5pKjGUvyFJJHhZ/yNUiEaJmvVqsTx0J0wy9+hgT/8fajf9v1lxAohmx/1/ev6u//tnZ/19/++CfncA3IaumHsB7q9C3HWKNk/0WPFVWzPzrxANcz2jdc+k4qIxiv3eoOevuSVTheSt3kjWzBXldvd8q6y5a0WFAoOKDM2UNmqsqAR8dYmUQl5AI8AIQLWs4AvOyq8ufPwI7JFr6Lto+cN6o52uhNxi1rxgjbJ5TMP8ObiWYQhNwdkrWKZq3ljgb596j1bTxCyKilpm399yu46X7oX77RdkGWjnh/NT9n9KgtGU9Fbl7u//waD/7v4/Oxns+38X9AGuxLrXm3blOHnFFeCPAnb7E0jRLSuw4hVrNDVdDmKB4lbye6oZoBVItuRKy6ee43yAMaO6k0yhr2SU9HqWSZqKNoX18VZwLeQdRGj9wt1fyf9K/0fhkMQZ6elHveP+H/hng3f3f9/f9/9OyBmK9knyZaXhsDiCgfkYS+rugZZ0xWtRU0g2TwLHmTG54sq8AcyIqPBj4fYJlpI2mpUeLCRjZjbgLSqXzAMtAM2gxVeDGRq3Gt8EvFk6FAqENJraDBslFvqBSobKJVClRMFxrpRQiqLbzpwFr5mCQ10xx802Fu6RBSkZrYE36I3BswgeOD4OOo2jCQcTL4wPD5WKuitNDM/imq/4BsGY2zoo47RTmIGJ04OVKPnCrMym1Xa3NVeV55Rm5vHbTiNTGaZ9fngmj2MhQbG6Nh7w5bHOdRud1UEUpzUF1ZsSWdyHSqzeZoIlWnSyQUhW2nQFlswifmeFNl6M+kLUtXjA1BCyKbnJSF2YcY51vRX3zOayPuZGaAx1HYI5gHZ7qhuRqijGfsucdcEQF8tLX6UjDTz2TaM51r4V0uL9OU0c8PmEQJaM8+sgJRBmMEuTL+GIjMANMty7HlyH+SSZ54AaaRDnN5CMIYhv4HMYjzyH/DZLSZZBkkI4nUUhGXkQxsNoPgrjK7hEuzjJIQrxwYdO8wQM4MZVSNBu7ExJOpzgNrgMozC/8WAc5rHxOUanAcyCNA+H8yhIYTZPZ0lGEH7kxEkcxuMUUciUxHkPUREKyBfcQDYJoshCBXOMPrXxDZPZTRpeTXKYJNGIIPOSOFEYXEZkDYVJDaMgnHowCqbBFbFWCXpJwahtorueEMtCvAB/wzxMYgdrMkziPMWth1mm+YvpdZgRD4I0zExBxmmC7k050SKxTtAuJmsvptTw5kRQxeznGdnGMiJBhL4yY/xaeX8x72lPe9rTT0V/APlm4rcAGAAA",
"length": 1089
}
}
}`,
)
req := httptest.NewRequest(http.MethodPut, "/{name}", bytes.NewReader(jsonBody))
wrt := httptest.NewRecorder()
lg := &logrus.Logger{
Out: os.Stdout,
// Level: "DEBUG",
Formatter: &logrus.TextFormatter{
FullTimestamp: true,
TimestampFormat: "2009-01-02 15:15:15",
},
}
cfg := config.Config{
RepoDir: "",
}
mfs := &storage.MockFs{}
mfs.GetIndexJsonFromStoreFunc = func(packageName string, registryPath string, lg *logrus.Logger) (string, bool, error) {
return string(jsonBody), true, nil
}
mfs.ReadIndexJsonFunc = func(fPath string, res *serviceidos.IndexJson, lg *logrus.Logger) error {
temp := serviceidos.IndexJson{
Versions: map[string]serviceidos.IndexJsonVersions{
"1.2.0": {
Version: "1.2.0",
Name: "@ookusanya/simplepackone",
},
},
}
*res = temp
return nil
}
mfs.WriteIndexJsonFunc = func(fPath string, res *serviceidos.IndexJson, lg *logrus.Logger) error {
return fmt.Errorf("Filesystem error")
}
vars := map[string]string{
"name": "@ookusanya%2Fsimplepackone",
}
req = mux.SetURLVars(req, vars)
Publish(lg, cfg, mfs)(wrt, req)
rs := wrt.Result()
assert.Equal(t, rs.StatusCode, http.StatusBadRequest)
defer rs.Body.Close()
body, err := io.ReadAll(rs.Body)
if err != nil {
t.Fatal(err)
}
bytes.TrimSpace(body)
assert.Equal(t, string(body), "Version 1.2.0 of package @ookusanya/simplepackone already exists!!\n\n")
})
t.Run("return `Internal Server` error if writing index.json fails", func(t *testing.T) {
jsonBody := []byte(
`{
"_id": "@ookusanya/simplepackone",
"name": "@ookusanya/simplepackone",
"description": "This is a very rough implementation of a private npm registry.",
"dist-tags": {
"latest": "1.3.0"
},
"versions": {
"1.3.0": {
"name": "@ookusanya/simplepackone",
"version": "1.3.0",
"description": "This is a very rough implementation of a private npm registry.",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"license": "MIT",
"files": null,
"readme": "# Gosimplenpm\n\nThis is a very rough implementation of a private npm registry.\n\n# Features\n\nTODO...\n\n# Enhancements\n\nTODO...\n\n# Work List\n\nTODO...",
"_id": "@ookusanya/simplepackone@1.2.0",
"_nodeVersion": "16.20.0",
"_npmVersion": "8.19.4",
"dist": {
"integrity": "sha512-coOiU+ywV/do/+HwK91mfuei9491yfQUedLWjspAjDa58RniJvQNTF/cXDp/sooVdpjgEbCqKVyLOju6C1i3pw==",
"shasum": "1adafdbe8878372c9f4b554bf30d5bfb1b7896c5",
"tarball": "http://localhost:4000/@ookusanya%2Fsimplepackone/-/@ookusanya%2Fsimplepackone-1.2.0.tgz"
},
"dependencies": {
"eslint": "^7.x",
"mocha": "^10.x",
"uuid": "^9.x"
}
}
},
"access": "",
"_attachments": {
"@ookusanya/simplepackone-1.3.0.tgz": {
"content_type": "application/octet-stream",
"data": "H4sIAAAAAAAC/+1XbWvjOBDuZ/+KwQtLCyZ10pfl+uncRGnMOnawne0VlgXVVmJtHctIcl849r/fSEmb9nof73LcXoaA0Lw9M6PMSG5pcUeX7Jg3JXvsfVcH/wD5vn9+egp/xbc0OIGDk7Nzv98/P/dRz+/7nwY+rgc7oE5pKjGUvyFJJHhZ/yNUiEaJmvVqsTx0J0wy9+hgT/8fajf9v1lxAohmx/1/ev6u//tnZ/19/++CfncA3IaumHsB7q9C3HWKNk/0WPFVWzPzrxANcz2jdc+k4qIxiv3eoOevuSVTheSt3kjWzBXldvd8q6y5a0WFAoOKDM2UNmqsqAR8dYmUQl5AI8AIQLWs4AvOyq8ufPwI7JFr6Lto+cN6o52uhNxi1rxgjbJ5TMP8ObiWYQhNwdkrWKZq3ljgb596j1bTxCyKilpm399yu46X7oX77RdkGWjnh/NT9n9KgtGU9Fbl7u//waD/7v4/Oxns+38X9AGuxLrXm3blOHnFFeCPAnb7E0jRLSuw4hVrNDVdDmKB4lbye6oZoBVItuRKy6ee43yAMaO6k0yhr2SU9HqWSZqKNoX18VZwLeQdRGj9wt1fyf9K/0fhkMQZ6elHveP+H/hng3f3f9/f9/9OyBmK9knyZaXhsDiCgfkYS+rugZZ0xWtRU0g2TwLHmTG54sq8AcyIqPBj4fYJlpI2mpUeLCRjZjbgLSqXzAMtAM2gxVeDGRq3Gt8EvFk6FAqENJraDBslFvqBSobKJVClRMFxrpRQiqLbzpwFr5mCQ10xx802Fu6RBSkZrYE36I3BswgeOD4OOo2jCQcTL4wPD5WKuitNDM/imq/4BsGY2zoo47RTmIGJ04OVKPnCrMym1Xa3NVeV55Rm5vHbTiNTGaZ9fngmj2MhQbG6Nh7w5bHOdRud1UEUpzUF1ZsSWdyHSqzeZoIlWnSyQUhW2nQFlswifmeFNl6M+kLUtXjA1BCyKbnJSF2YcY51vRX3zOayPuZGaAx1HYI5gHZ7qhuRqijGfsucdcEQF8tLX6UjDTz2TaM51r4V0uL9OU0c8PmEQJaM8+sgJRBmMEuTL+GIjMANMty7HlyH+SSZ54AaaRDnN5CMIYhv4HMYjzyH/DZLSZZBkkI4nUUhGXkQxsNoPgrjK7hEuzjJIQrxwYdO8wQM4MZVSNBu7ExJOpzgNrgMozC/8WAc5rHxOUanAcyCNA+H8yhIYTZPZ0lGEH7kxEkcxuMUUciUxHkPUREKyBfcQDYJoshCBXOMPrXxDZPZTRpeTXKYJNGIIPOSOFEYXEZkDYVJDaMgnHowCqbBFbFWCXpJwahtorueEMtCvAB/wzxMYgdrMkziPMWth1mm+YvpdZgRD4I0zExBxmmC7k050SKxTtAuJmsvptTw5kRQxeznGdnGMiJBhL4yY/xaeX8x72lPe9rTT0V/APlm4rcAGAAA",
"length": 1089
}
}
}`,
)
req := httptest.NewRequest(http.MethodPut, "/{name}", bytes.NewReader(jsonBody))
wrt := httptest.NewRecorder()
lg := &logrus.Logger{
Out: os.Stdout,
// Level: "DEBUG",
Formatter: &logrus.TextFormatter{
FullTimestamp: true,
TimestampFormat: "2009-01-02 15:15:15",
},
}
cfg := config.Config{
RepoDir: "",
}
mfs := &storage.MockFs{}
mfs.GetIndexJsonFromStoreFunc = func(packageName string, registryPath string, lg *logrus.Logger) (string, bool, error) {
return string(jsonBody), true, nil
}
mfs.ReadIndexJsonFunc = func(fPath string, res *serviceidos.IndexJson, lg *logrus.Logger) error {
temp := serviceidos.IndexJson{
Versions: map[string]serviceidos.IndexJsonVersions{
"1.2.0": {
Version: "1.2.0",
Name: "@ookusanya/simplepackone",
},
},
DistTags: map[string]string{
"latest": "1.2.0",
},
TimesPackage: map[string]string{
"modified": "",
"created": "",
},
}
*res = temp
return nil
}
mfs.WriteIndexJsonFunc = func(fPath string, res *serviceidos.IndexJson, lg *logrus.Logger) error {
return fmt.Errorf("Filesystem error")
}
vars := map[string]string{
"name": "@ookusanya%2Fsimplepackone",
}
req = mux.SetURLVars(req, vars)
Publish(lg, cfg, mfs)(wrt, req)
rs := wrt.Result()
assert.Equal(t, rs.StatusCode, http.StatusInternalServerError)
defer rs.Body.Close()
body, err := io.ReadAll(rs.Body)
if err != nil {
t.Fatal(err)
}
bytes.TrimSpace(body)
assert.Equal(t, string(body), "Filesystem error\n")
})
t.Run("return `Internal Server` error if writing tar package fails", func(t *testing.T) {
jsonBody := []byte(
`{
"_id": "@ookusanya/simplepackone",
"name": "@ookusanya/simplepackone",
"description": "This is a very rough implementation of a private npm registry.",
"dist-tags": {
"latest": "1.3.0"
},
"versions": {
"1.3.0": {
"name": "@ookusanya/simplepackone",
"version": "1.3.0",
"description": "This is a very rough implementation of a private npm registry.",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"license": "MIT",
"files": null,
"readme": "# Gosimplenpm\n\nThis is a very rough implementation of a private npm registry.\n\n# Features\n\nTODO...\n\n# Enhancements\n\nTODO...\n\n# Work List\n\nTODO...",
"_id": "@ookusanya/simplepackone@1.2.0",
"_nodeVersion": "16.20.0",
"_npmVersion": "8.19.4",
"dist": {
"integrity": "sha512-coOiU+ywV/do/+HwK91mfuei9491yfQUedLWjspAjDa58RniJvQNTF/cXDp/sooVdpjgEbCqKVyLOju6C1i3pw==",
"shasum": "1adafdbe8878372c9f4b554bf30d5bfb1b7896c5",
"tarball": "http://localhost:4000/@ookusanya%2Fsimplepackone/-/@ookusanya%2Fsimplepackone-1.2.0.tgz"
},
"dependencies": {
"eslint": "^7.x",
"mocha": "^10.x",
"uuid": "^9.x"
}
}
},
"access": "",
"_attachments": {
"@ookusanya/simplepackone-1.3.0.tgz": {
"content_type": "application/octet-stream",
"data": "H4sIAAAAAAAC/+1XbWvjOBDuZ/+KwQtLCyZ10pfl+uncRGnMOnawne0VlgXVVmJtHctIcl849r/fSEmb9nof73LcXoaA0Lw9M6PMSG5pcUeX7Jg3JXvsfVcH/wD5vn9+egp/xbc0OIGDk7Nzv98/P/dRz+/7nwY+rgc7oE5pKjGUvyFJJHhZ/yNUiEaJmvVqsTx0J0wy9+hgT/8fajf9v1lxAohmx/1/ev6u//tnZ/19/++CfncA3IaumHsB7q9C3HWKNk/0WPFVWzPzrxANcz2jdc+k4qIxiv3eoOevuSVTheSt3kjWzBXldvd8q6y5a0WFAoOKDM2UNmqsqAR8dYmUQl5AI8AIQLWs4AvOyq8ufPwI7JFr6Lto+cN6o52uhNxi1rxgjbJ5TMP8ObiWYQhNwdkrWKZq3ljgb596j1bTxCyKilpm399yu46X7oX77RdkGWjnh/NT9n9KgtGU9Fbl7u//waD/7v4/Oxns+38X9AGuxLrXm3blOHnFFeCPAnb7E0jRLSuw4hVrNDVdDmKB4lbye6oZoBVItuRKy6ee43yAMaO6k0yhr2SU9HqWSZqKNoX18VZwLeQdRGj9wt1fyf9K/0fhkMQZ6elHveP+H/hng3f3f9/f9/9OyBmK9knyZaXhsDiCgfkYS+rugZZ0xWtRU0g2TwLHmTG54sq8AcyIqPBj4fYJlpI2mpUeLCRjZjbgLSqXzAMtAM2gxVeDGRq3Gt8EvFk6FAqENJraDBslFvqBSobKJVClRMFxrpRQiqLbzpwFr5mCQ10xx802Fu6RBSkZrYE36I3BswgeOD4OOo2jCQcTL4wPD5WKuitNDM/imq/4BsGY2zoo47RTmIGJ04OVKPnCrMym1Xa3NVeV55Rm5vHbTiNTGaZ9fngmj2MhQbG6Nh7w5bHOdRud1UEUpzUF1ZsSWdyHSqzeZoIlWnSyQUhW2nQFlswifmeFNl6M+kLUtXjA1BCyKbnJSF2YcY51vRX3zOayPuZGaAx1HYI5gHZ7qhuRqijGfsucdcEQF8tLX6UjDTz2TaM51r4V0uL9OU0c8PmEQJaM8+sgJRBmMEuTL+GIjMANMty7HlyH+SSZ54AaaRDnN5CMIYhv4HMYjzyH/DZLSZZBkkI4nUUhGXkQxsNoPgrjK7hEuzjJIQrxwYdO8wQM4MZVSNBu7ExJOpzgNrgMozC/8WAc5rHxOUanAcyCNA+H8yhIYTZPZ0lGEH7kxEkcxuMUUciUxHkPUREKyBfcQDYJoshCBXOMPrXxDZPZTRpeTXKYJNGIIPOSOFEYXEZkDYVJDaMgnHowCqbBFbFWCXpJwahtorueEMtCvAB/wzxMYgdrMkziPMWth1mm+YvpdZgRD4I0zExBxmmC7k050SKxTtAuJmsvptTw5kRQxeznGdnGMiJBhL4yY/xaeX8x72lPe9rTT0V/APlm4rcAGAAA",
"length": 1089
}
}
}`,
)
req := httptest.NewRequest(http.MethodPut, "/{name}", bytes.NewReader(jsonBody))
wrt := httptest.NewRecorder()
lg := &logrus.Logger{
Out: os.Stdout,
// Level: "DEBUG",
Formatter: &logrus.TextFormatter{
FullTimestamp: true,
TimestampFormat: "2009-01-02 15:15:15",
},
}
cfg := config.Config{
RepoDir: "",
}
mfs := &storage.MockFs{}
mfs.GetIndexJsonFromStoreFunc = func(packageName string, registryPath string, lg *logrus.Logger) (string, bool, error) {
return string(jsonBody), true, nil
}
mfs.ReadIndexJsonFunc = func(fPath string, res *serviceidos.IndexJson, lg *logrus.Logger) error {
temp := serviceidos.IndexJson{
Versions: map[string]serviceidos.IndexJsonVersions{
"1.2.0": {
Version: "1.2.0",
Name: "@ookusanya/simplepackone",
},
},
DistTags: map[string]string{
"latest": "1.2.0",
},
TimesPackage: map[string]string{
"modified": "",
"created": "",
},
}
*res = temp
return nil
}
mfs.WriteIndexJsonFunc = func(fPath string, res *serviceidos.IndexJson, lg *logrus.Logger) error {
return nil
}
mfs.WritePackageToStoreFunc = func(fPath string, data string, lg *logrus.Logger) error {
return fmt.Errorf("Filesystem error")
}
vars := map[string]string{
"name": "@ookusanya%2Fsimplepackone",
}
req = mux.SetURLVars(req, vars)
Publish(lg, cfg, mfs)(wrt, req)
rs := wrt.Result()
assert.Equal(t, rs.StatusCode, http.StatusInternalServerError)
defer rs.Body.Close()
body, err := io.ReadAll(rs.Body)
if err != nil {
t.Fatal(err)
}
bytes.TrimSpace(body)
assert.Equal(t, string(body), "Filesystem error\n")
})
t.Run("return 201 Created if publish is successful", func(t *testing.T) {
jsonBody := []byte(
`{
"_id": "@ookusanya/simplepackone",
"name": "@ookusanya/simplepackone",
"description": "This is a very rough implementation of a private npm registry.",
"dist-tags": {
"latest": "1.3.0"
},
"versions": {
"1.3.0": {
"name": "@ookusanya/simplepackone",
"version": "1.3.0",
"description": "This is a very rough implementation of a private npm registry.",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"license": "MIT",
"files": null,
"readme": "# Gosimplenpm\n\nThis is a very rough implementation of a private npm registry.\n\n# Features\n\nTODO...\n\n# Enhancements\n\nTODO...\n\n# Work List\n\nTODO...",
"_id": "@ookusanya/simplepackone@1.2.0",
"_nodeVersion": "16.20.0",
"_npmVersion": "8.19.4",
"dist": {
"integrity": "sha512-coOiU+ywV/do/+HwK91mfuei9491yfQUedLWjspAjDa58RniJvQNTF/cXDp/sooVdpjgEbCqKVyLOju6C1i3pw==",
"shasum": "1adafdbe8878372c9f4b554bf30d5bfb1b7896c5",
"tarball": "http://localhost:4000/@ookusanya%2Fsimplepackone/-/@ookusanya%2Fsimplepackone-1.2.0.tgz"
},
"dependencies": {
"eslint": "^7.x",
"mocha": "^10.x",
"uuid": "^9.x"
}
}
},
"access": "",
"_attachments": {
"@ookusanya/simplepackone-1.3.0.tgz": {
"content_type": "application/octet-stream",
"data": "H4sIAAAAAAAC/+1XbWvjOBDuZ/+KwQtLCyZ10pfl+uncRGnMOnawne0VlgXVVmJtHctIcl849r/fSEmb9nof73LcXoaA0Lw9M6PMSG5pcUeX7Jg3JXvsfVcH/wD5vn9+egp/xbc0OIGDk7Nzv98/P/dRz+/7nwY+rgc7oE5pKjGUvyFJJHhZ/yNUiEaJmvVqsTx0J0wy9+hgT/8fajf9v1lxAohmx/1/ev6u//tnZ/19/++CfncA3IaumHsB7q9C3HWKNk/0WPFVWzPzrxANcz2jdc+k4qIxiv3eoOevuSVTheSt3kjWzBXldvd8q6y5a0WFAoOKDM2UNmqsqAR8dYmUQl5AI8AIQLWs4AvOyq8ufPwI7JFr6Lto+cN6o52uhNxi1rxgjbJ5TMP8ObiWYQhNwdkrWKZq3ljgb596j1bTxCyKilpm399yu46X7oX77RdkGWjnh/NT9n9KgtGU9Fbl7u//waD/7v4/Oxns+38X9AGuxLrXm3blOHnFFeCPAnb7E0jRLSuw4hVrNDVdDmKB4lbye6oZoBVItuRKy6ee43yAMaO6k0yhr2SU9HqWSZqKNoX18VZwLeQdRGj9wt1fyf9K/0fhkMQZ6elHveP+H/hng3f3f9/f9/9OyBmK9knyZaXhsDiCgfkYS+rugZZ0xWtRU0g2TwLHmTG54sq8AcyIqPBj4fYJlpI2mpUeLCRjZjbgLSqXzAMtAM2gxVeDGRq3Gt8EvFk6FAqENJraDBslFvqBSobKJVClRMFxrpRQiqLbzpwFr5mCQ10xx802Fu6RBSkZrYE36I3BswgeOD4OOo2jCQcTL4wPD5WKuitNDM/imq/4BsGY2zoo47RTmIGJ04OVKPnCrMym1Xa3NVeV55Rm5vHbTiNTGaZ9fngmj2MhQbG6Nh7w5bHOdRud1UEUpzUF1ZsSWdyHSqzeZoIlWnSyQUhW2nQFlswifmeFNl6M+kLUtXjA1BCyKbnJSF2YcY51vRX3zOayPuZGaAx1HYI5gHZ7qhuRqijGfsucdcEQF8tLX6UjDTz2TaM51r4V0uL9OU0c8PmEQJaM8+sgJRBmMEuTL+GIjMANMty7HlyH+SSZ54AaaRDnN5CMIYhv4HMYjzyH/DZLSZZBkkI4nUUhGXkQxsNoPgrjK7hEuzjJIQrxwYdO8wQM4MZVSNBu7ExJOpzgNrgMozC/8WAc5rHxOUanAcyCNA+H8yhIYTZPZ0lGEH7kxEkcxuMUUciUxHkPUREKyBfcQDYJoshCBXOMPrXxDZPZTRpeTXKYJNGIIPOSOFEYXEZkDYVJDaMgnHowCqbBFbFWCXpJwahtorueEMtCvAB/wzxMYgdrMkziPMWth1mm+YvpdZgRD4I0zExBxmmC7k050SKxTtAuJmsvptTw5kRQxeznGdnGMiJBhL4yY/xaeX8x72lPe9rTT0V/APlm4rcAGAAA",
"length": 1089
}
}
}`,
)
req := httptest.NewRequest(http.MethodPut, "/{name}", bytes.NewReader(jsonBody))
wrt := httptest.NewRecorder()
lg := &logrus.Logger{
Out: os.Stdout,
// Level: "DEBUG",
Formatter: &logrus.TextFormatter{
FullTimestamp: true,
TimestampFormat: "2009-01-02 15:15:15",
},
}
cfg := config.Config{
RepoDir: "",
}
mfs := &storage.MockFs{}
mfs.GetIndexJsonFromStoreFunc = func(packageName string, registryPath string, lg *logrus.Logger) (string, bool, error) {
return string(jsonBody), false, nil
}
mfs.WriteIndexJsonFunc = func(fPath string, res *serviceidos.IndexJson, lg *logrus.Logger) error {
return nil
}
mfs.WritePackageToStoreFunc = func(fPath string, data string, lg *logrus.Logger) error {
return nil
}
vars := map[string]string{
"name": "@ookusanya%2Fsimplepackone",
}
req = mux.SetURLVars(req, vars)
Publish(lg, cfg, mfs)(wrt, req)
rs := wrt.Result()
assert.Equal(t, rs.StatusCode, http.StatusCreated)
defer rs.Body.Close()
body, err := io.ReadAll(rs.Body)
if err != nil {
t.Fatal(err)
}
bytes.TrimSpace(body)
assert.Equal(t, string(body), "{\"ok\":true,\"package_name\":\"@ookusanya/simplepackone\"}")
})
}
func TestIntegrationPublishNormal(t *testing.T) {
if testing.Short() {
t.Skip("Skipping publishPackage integration test")
}
token := "0N89nr/hmKXoBzG]R{fKH%YE1X"
tmpDir := t.TempDir()
t.Logf("Temp Dir: %s", tmpDir)
indexJsonFp := "intestdata/publish/normal/index.json"
isEmpty := IsDirEmpty(t, tmpDir)
assert.Equal(t, true, isEmpty)
cfg := config.Config{
RepoDir: tmpDir,
Token: token,
}
app := newTestApp(t, cfg)
app.Routes()
ts := newTestServer(t, app.Mux)
defer ts.Close()
dataToSend := readTestFile(t, indexJsonFp)
code, _, body := ts.put(t, fmt.Sprintf("/%s", url.PathEscape("@df/simplepackone")), token, string(dataToSend))
assert.Equal(t, code, http.StatusCreated)
isEmpty = IsDirEmpty(t, tmpDir)
assert.Equal(t, false, isEmpty)
// t.Logf("Body ==> %s", string(body))
filePaths := listDir(t, tmpDir, false)
assert.Equal(t, true, containsSub(filePaths, "index.json"))
assert.Equal(t, true, containsSub(filePaths, "simplepackone-1.0.0"))
assert.NotEmpty(t, string(body))
}
func TestIntegrationPublishOverwrite(t *testing.T) {
if testing.Short() {
t.Skip("Skipping publishPackage integration test")
}
token := "0N89nr/hmKXoBzG]R{fKH%YE1X"
tmpDir := t.TempDir()
t.Logf("Temp Dir: %s", tmpDir)
// Copy initial package
indexJsonFp := "intestdata/publish/normal/index.json"
tgzFp := "intestdata/get/simplepackone-1.0.0.tgz"
mkDir(t, fmt.Sprintf("%s/@df/simplepackone", tmpDir))
cpFile(t, indexJsonFp, fmt.Sprintf("%s/@df/simplepackone/index.json", tmpDir))
cpFile(t, tgzFp, fmt.Sprintf("%s/@df/simplepackone/simplepackone-1.0.0.tgz", tmpDir))
isEmpty := IsDirEmpty(t, tmpDir)
assert.Equal(t, false, isEmpty)
indexJsonFp = "intestdata/publish/overwrite/index.json"
cfg := config.Config{
RepoDir: tmpDir,
Token: token,
}
app := newTestApp(t, cfg)
app.Routes()
ts := newTestServer(t, app.Mux)
defer ts.Close()
dataToSend := readTestFile(t, indexJsonFp)
code, _, body := ts.put(t, fmt.Sprintf("/%s", url.PathEscape("@df/simplepackone")), token, string(dataToSend))
assert.Equal(t, code, http.StatusCreated)
filePaths := listDir(t, tmpDir, false)
assert.Equal(t, true, containsSub(filePaths, "index.json"))
assert.Equal(t, true, containsSub(filePaths, "simplepackone-1.0.0"))
assert.Equal(t, true, containsSub(filePaths, "simplepackone-1.9.0"))
assert.NotEmpty(t, string(body))
}