mirror of
https://github.com/go-vikunja/vikunja.git
synced 2026-11-09 00:22:38 -06:00
- Reject a config that maps a column more than once, already when the import is started or previewed. - Import repeated labels of a row once and reject rows with more than MaxLabelsPerTask (100) labels. - Count items while converting rows so a file over the import item limit fails before the whole structure is built. - Walk mappings sorted by column so a row only visits the cells it has.
133 lines
4.0 KiB
Go
133 lines
4.0 KiB
Go
// Vikunja is a to-do list application to facilitate your life.
|
|
// Copyright 2018-present Vikunja and contributors. All rights reserved.
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU Affero General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU Affero General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Affero General Public License
|
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
// External test package so errors from packages importing models can be covered.
|
|
package models_test
|
|
|
|
import (
|
|
"encoding/json"
|
|
"os"
|
|
"regexp"
|
|
"strconv"
|
|
"testing"
|
|
|
|
"code.vikunja.io/api/pkg/models"
|
|
"code.vikunja.io/api/pkg/modules/migration"
|
|
"code.vikunja.io/api/pkg/user"
|
|
"code.vikunja.io/api/pkg/web"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
var i18nPlaceholderPattern = regexp.MustCompile(`\{(\w+)}`)
|
|
|
|
func loadI18nErrorMessages(t *testing.T) map[string]string {
|
|
t.Helper()
|
|
|
|
raw, err := os.ReadFile("../../frontend/src/i18n/lang/en.json")
|
|
require.NoError(t, err)
|
|
|
|
var lang struct {
|
|
Error map[string]string `json:"error"`
|
|
}
|
|
require.NoError(t, json.Unmarshal(raw, &lang))
|
|
|
|
return lang.Error
|
|
}
|
|
|
|
func placeholderNames(message string) map[string]bool {
|
|
names := map[string]bool{}
|
|
for _, match := range i18nPlaceholderPattern.FindAllStringSubmatch(message, -1) {
|
|
names[match[1]] = true
|
|
}
|
|
return names
|
|
}
|
|
|
|
// I18nParams keys must equal the {placeholder} names in frontend/src/i18n/lang/en.json.
|
|
func TestI18nParamsContract(t *testing.T) {
|
|
i18nMessages := loadI18nErrorMessages(t)
|
|
|
|
tests := []struct {
|
|
name string
|
|
err web.HTTPErrorProcessor
|
|
expectedCode int
|
|
}{
|
|
{
|
|
name: "ErrInvalidTimezone",
|
|
err: models.ErrInvalidTimezone{Name: "x"},
|
|
expectedCode: models.ErrCodeInvalidTimezone,
|
|
},
|
|
{
|
|
name: "ErrInvalidAPITokenPermission",
|
|
err: &models.ErrInvalidAPITokenPermission{Group: "g", Permission: "p"},
|
|
expectedCode: models.ErrCodeInvalidAPITokenPermission,
|
|
},
|
|
{
|
|
name: "user.ErrInvalidClaimData",
|
|
err: &user.ErrInvalidClaimData{Field: "f", Type: "t"},
|
|
expectedCode: user.ErrCodeInvalidClaimData,
|
|
},
|
|
{
|
|
name: "user.ErrInvalidTimezone",
|
|
err: user.ErrInvalidTimezone{Name: "x"},
|
|
expectedCode: user.ErrorCodeInvalidTimezone,
|
|
},
|
|
{
|
|
name: "migration.ErrCSVDuplicateColumnMapping",
|
|
err: &migration.ErrCSVDuplicateColumnMapping{Column: 1},
|
|
expectedCode: migration.ErrCodeCSVDuplicateColumnMapping,
|
|
},
|
|
{
|
|
name: "migration.ErrCSVTooManyLabels",
|
|
err: &migration.ErrCSVTooManyLabels{Row: 1, MaxLabels: 1},
|
|
expectedCode: migration.ErrCodeCSVTooManyLabels,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
httpErr := tt.err.HTTPError()
|
|
assert.Equal(t, tt.expectedCode, httpErr.Code)
|
|
|
|
message, ok := i18nMessages[strconv.Itoa(tt.expectedCode)]
|
|
require.True(t, ok, "no en.json error message found for code %d", tt.expectedCode)
|
|
|
|
expectedParams := placeholderNames(message)
|
|
actualParams := map[string]bool{}
|
|
for key := range httpErr.I18nParams {
|
|
actualParams[key] = true
|
|
}
|
|
|
|
assert.Equal(t, expectedParams, actualParams)
|
|
})
|
|
}
|
|
|
|
coveredCodes := map[string]bool{}
|
|
for _, tt := range tests {
|
|
coveredCodes[strconv.Itoa(tt.expectedCode)] = true
|
|
}
|
|
|
|
parametrisedCodes := map[string]bool{}
|
|
for code, message := range i18nMessages {
|
|
if len(placeholderNames(message)) > 0 {
|
|
parametrisedCodes[code] = true
|
|
}
|
|
}
|
|
|
|
assert.Equal(t, parametrisedCodes, coveredCodes, "every parametrised en.json error message must have a corresponding I18nParams test case")
|
|
}
|