Add Marshal/Unmarshal

This commit is contained in:
andrea 2023-11-20 14:14:09 +01:00
parent 3196982a64
commit ac95b38fe8
13 changed files with 313 additions and 363 deletions

View file

@ -1,5 +1,7 @@
package models
import "encoding/json"
type Filter struct {
Tags []*Tag
}
@ -28,3 +30,12 @@ func (c *Collection) SetID(id string) {
func (c *Collection) GetHash() string {
return ""
}
func (c *Collection) Marshal() ([]byte, error) {
return json.Marshal(c)
}
func (c *Collection) Unmarshal(data []byte) error {
return json.Unmarshal(data, c)
}

View file

@ -42,11 +42,13 @@ Question text with #tag1 #tag2 (3).
CorrectPos: 0,
}
quiz, _, err := MarkdownToQuiz(markdown)
q := new(Quiz)
err := MarkdownToQuiz(q, markdown)
t.Nil(err, fmt.Sprintf("Quiz should be parsed without errors: %v", err))
if !t.Failed() {
t.True(reflect.DeepEqual(quiz, expectedQuiz), fmt.Sprintf("Expected %+v, got %+v", expectedQuiz, quiz))
t.True(reflect.DeepEqual(q, expectedQuiz), fmt.Sprintf("Expected %+v got %+v", expectedQuiz, q))
}
}

View file

@ -2,6 +2,7 @@ package models
import (
"crypto/sha256"
"encoding/json"
"fmt"
"strings"
)
@ -42,3 +43,12 @@ func (p *Participant) AttributesToSlice() []string {
return result
}
func (p *Participant) Marshal() ([]byte, error) {
return json.Marshal(p)
}
func (p *Participant) Unmarshal(data []byte) error {
return json.Unmarshal(data, p)
}

View file

@ -23,10 +23,10 @@ type Quiz struct {
Type int `json:"type"`
}
func MarkdownToQuiz(markdown string) (*Quiz, *Meta, error) {
func MarkdownToQuiz(quiz *Quiz, markdown string) error {
meta, remainingMarkdown, err := ParseMetaHeaderFromMarkdown(markdown)
if err != nil {
return nil, nil, err
return err
}
lines := strings.Split(remainingMarkdown, "\n")
@ -50,21 +50,25 @@ func MarkdownToQuiz(markdown string) (*Quiz, *Meta, error) {
questionText = strings.TrimRight(questionText, "\n")
if questionText == "" {
return nil, nil, fmt.Errorf("Question text should not be empty.")
return fmt.Errorf("Question text should not be empty.")
}
if len(answers) < 2 {
return nil, nil, fmt.Errorf("Number of answers should be at least 2 but parsed answers are %d.", len(answers))
return fmt.Errorf("Number of answers should be at least 2 but parsed answers are %d.", len(answers))
}
question := &Question{Text: questionText}
quiz := &Quiz{Question: question, Answers: answers, CorrectPos: 0}
quiz.Question = question
quiz.Answers = answers
//quiz = &Quiz{Question: question, Answers: answers, CorrectPos: 0}
if meta != nil {
quiz.Meta = *meta
}
return quiz, meta, nil
return nil
}
func QuizToMarkdown(quiz *Quiz) (string, error) {
@ -108,6 +112,17 @@ func (q *Quiz) GetHash() string {
return q.calculateHash()
}
func (q *Quiz) Marshal() ([]byte, error) {
result, err := QuizToMarkdown(q)
return []byte(result), err
}
func (q *Quiz) Unmarshal(data []byte) error {
return MarkdownToQuiz(q, string(data))
}
func (q *Quiz) calculateHash() string {
result := make([]string, 0)

View file

@ -1,54 +1,22 @@
package file
import (
"encoding/json"
"os"
"path/filepath"
"git.andreafazzi.eu/andrea/probo/models"
"git.andreafazzi.eu/andrea/probo/store"
)
type CollectionFileStore = FileStore[*models.Collection, *store.Store[*models.Collection]]
var DefaultCollectionDir = filepath.Join(BaseDir, CollectionsDir)
func NewCollectionFileStore(config *FileStoreConfig[*models.Collection, *store.CollectionStore]) (*CollectionFileStore, error) {
return NewFileStore[*models.Collection](config, store.NewStore[*models.Collection]())
}
func DefaultUnmarshalCollectionFunc(s *store.Store[*models.Collection], filepath string, content []byte) (*models.Collection, error) {
collection := new(models.Collection)
err := json.Unmarshal(content, &collection)
if err != nil {
return nil, err
}
func NewDefaultCollectionFileStore() (*CollectionFileStore, error) {
return NewCollectionFileStore(
&FileStoreConfig[*models.Collection, *store.CollectionStore]{
FilePathConfig: FilePathConfig{DefaultBaseDir, "collection", ".json"},
IndexDirFunc: DefaultIndexDirFunc[*models.Collection, *store.CollectionStore],
},
)
c, err := s.Create(collection)
if err != nil {
return nil, err
}
return c, nil
}
func DefaultMarshalCollectionFunc(s *store.Store[*models.Collection], filePath string, collection *models.Collection) error {
jsonData, err := json.Marshal(collection)
if err != nil {
return err
}
file, err := os.Create(filePath)
if err != nil {
return err
}
defer file.Close()
_, err = file.Write(jsonData)
if err != nil {
return err
}
return nil
}

View file

@ -48,14 +48,7 @@ func (t *collectionTestSuite) TestCreateCollection() {
},
})
store, err := NewCollectionFileStore(
&FileStoreConfig[*models.Collection, *store.CollectionStore]{
FilePathConfig: FilePathConfig{"testdata", "collection", ".json"},
IndexDirFunc: DefaultIndexDirFunc[*models.Collection, *store.CollectionStore],
UnmarshalFunc: DefaultUnmarshalCollectionFunc,
MarshalFunc: DefaultMarshalCollectionFunc,
},
)
store, err := NewDefaultCollectionFileStore()
t.Nil(err)
c := new(models.Collection)

22
store/file/defaults.go Normal file
View file

@ -0,0 +1,22 @@
package file
import "path/filepath"
var (
DefaultBaseDir = "data"
DefaultQuizzesSubdir = "quizzes"
DefaultCollectionsSubdir = "collections"
DefaultParticipantsSubdir = "participants"
)
func GetDefaultQuizzesDir() string {
return filepath.Join(DefaultBaseDir, DefaultQuizzesSubdir)
}
func GetDefaultCollectionsDir() string {
return filepath.Join(DefaultBaseDir, DefaultCollectionsSubdir)
}
func GetDefaultParticipantsDir() string {
return filepath.Join(DefaultBaseDir, DefaultParticipantsSubdir)
}

View file

@ -1,7 +1,6 @@
package file
import (
"encoding/json"
"errors"
"fmt"
"io/fs"
@ -13,17 +12,19 @@ import (
"git.andreafazzi.eu/andrea/probo/store"
)
type IndexDirFunc[T store.Storable, K Storer[T]] func(s *FileStore[T, K]) error
type IndexDirFunc[T FileStorable, K Storer[T]] func(s *FileStore[T, K]) error
var (
ErrorMetaHeaderIsNotPresent = errors.New("Meta header was not found in file.")
BaseDir = "data"
QuizzesDir = "quizzes"
CollectionsDir = "collections"
ParticipantsDir = "participants"
)
type FileStorable interface {
store.Storable
Marshal() ([]byte, error)
Unmarshal([]byte) error
}
type Storer[T store.Storable] interface {
store.Storer[T]
}
@ -34,16 +35,13 @@ type FilePathConfig struct {
FileSuffix string
}
type FileStoreConfig[T store.Storable, K Storer[T]] struct {
type FileStoreConfig[T FileStorable, K Storer[T]] struct {
FilePathConfig
FilepathFunc func(T, *FilePathConfig) string
UnmarshalFunc func(K, string, []byte) (T, error)
MarshalFunc func(K, string, T) error
IndexDirFunc func(*FileStore[T, K]) error
NoIndexOnCreate bool
}
type FileStore[T store.Storable, K Storer[T]] struct {
type FileStore[T FileStorable, K Storer[T]] struct {
*FileStoreConfig[T, K]
Storer K
@ -52,43 +50,7 @@ type FileStore[T store.Storable, K Storer[T]] struct {
paths map[string]string
}
func DefaultJSONUnmarshalFunc[T store.Storable, K Storer[T]](s K, filepath string, content []byte) (T, error) {
entity := new(T)
err := json.Unmarshal(content, &entity)
if err != nil {
return *entity, err
}
c, err := s.Create(*entity)
if err != nil {
return c, err
}
return c, nil
}
func DefaultJSONMarshalFunc[T store.Storable, K Storer[T]](s K, filePath string, entity T) error {
jsonData, err := json.Marshal(entity)
if err != nil {
return err
}
file, err := os.Create(filePath)
if err != nil {
return err
}
defer file.Close()
_, err = file.Write(jsonData)
if err != nil {
return err
}
return nil
}
func DefaultIndexDirFunc[T store.Storable, K Storer[T]](s *FileStore[T, K]) error {
func DefaultIndexDirFunc[T FileStorable, K Storer[T]](s *FileStore[T, K]) error {
files, err := os.ReadDir(s.Dir)
if err != nil {
return err
@ -112,19 +74,26 @@ func DefaultIndexDirFunc[T store.Storable, K Storer[T]](s *FileStore[T, K]) erro
return err
}
entity, err := s.UnmarshalFunc(s.Storer, fullPath, content)
var entity T
err = entity.Unmarshal(content)
if err != nil {
return err
}
s.SetPath(entity, fullPath)
mEntity, err := s.Create(entity)
if err != nil {
return err
}
s.SetPath(mEntity, fullPath)
}
return nil
}
func NewFileStore[T store.Storable, K Storer[T]](config *FileStoreConfig[T, K], storer K) (*FileStore[T, K], error) {
func NewFileStore[T FileStorable, K Storer[T]](config *FileStoreConfig[T, K], storer K) (*FileStore[T, K], error) {
store := &FileStore[T, K]{
FileStoreConfig: config,
Storer: storer,
@ -148,15 +117,21 @@ func (s *FileStore[T, K]) Create(entity T) (T, error) {
return e, err
}
var filePath string
filePath := filepath.Join(s.Dir, fmt.Sprintf("%s_%v%s", s.FilePrefix, e.GetID(), s.FileSuffix))
if s.FilepathFunc == nil {
filePath = filepath.Join(s.Dir, fmt.Sprintf("%s_%v%s", s.FilePrefix, e.GetID(), s.FileSuffix))
} else {
filePath = s.FilepathFunc(entity, &s.FilePathConfig)
data, err := e.Marshal()
if err != nil {
return e, err
}
err = s.MarshalFunc(s.Storer, filePath, e)
file, err := os.Create(filePath)
if err != nil {
return e, err
}
defer file.Close()
_, err = file.Write(data)
if err != nil {
return e, err
}
@ -174,7 +149,19 @@ func (s *FileStore[T, K]) Update(entity T, id string) (T, error) {
filePath := s.GetPath(e)
err = s.MarshalFunc(s.Storer, filePath, e)
data, err := e.Marshal()
if err != nil {
return e, err
}
file, err := os.Create(filePath)
if err != nil {
return e, err
}
defer file.Close()
_, err = file.Write(data)
if err != nil {
return e, err
}

View file

@ -9,6 +9,8 @@ import (
var testdataDir = "./testdata"
func TestRunner(t *testing.T) {
DefaultBaseDir = "testdata"
prettytest.Run(
t,
new(quizTestSuite),

View file

@ -1,9 +1,6 @@
package file
import (
"encoding/json"
"os"
"git.andreafazzi.eu/andrea/probo/models"
"git.andreafazzi.eu/andrea/probo/store"
)
@ -13,39 +10,3 @@ type ParticipantFileStore = FileStore[*models.Participant, *store.Store[*models.
func NewParticipantFileStore(config *FileStoreConfig[*models.Participant, *store.Store[*models.Participant]]) (*ParticipantFileStore, error) {
return NewFileStore[*models.Participant](config, store.NewStore[*models.Participant]())
}
func DefaultUnmarshalParticipantFunc(s *store.Store[*models.Participant], filepath string, content []byte) (*models.Participant, error) {
participant := new(models.Participant)
err := json.Unmarshal(content, &participant)
if err != nil {
return nil, err
}
c, err := s.Create(participant)
if err != nil {
return nil, err
}
return c, nil
}
func DefaultMarshalParticipantFunc(s *store.Store[*models.Participant], filePath string, participant *models.Participant) error {
jsonData, err := json.Marshal(participant)
if err != nil {
return err
}
file, err := os.Create(filePath)
if err != nil {
return err
}
defer file.Close()
_, err = file.Write(jsonData)
if err != nil {
return err
}
return nil
}

View file

@ -18,8 +18,6 @@ func (t *participantTestSuite) TestCreate() {
&FileStoreConfig[*models.Participant, *store.ParticipantStore]{
FilePathConfig: filePathConfig,
IndexDirFunc: DefaultIndexDirFunc[*models.Participant, *store.ParticipantStore],
UnmarshalFunc: DefaultJSONUnmarshalFunc[*models.Participant, *store.ParticipantStore],
MarshalFunc: DefaultJSONMarshalFunc[*models.Participant, *store.ParticipantStore],
})
t.Nil(err)

View file

@ -5,7 +5,9 @@ import (
"bytes"
"errors"
"io"
"io/fs"
"os"
"path/filepath"
"strings"
"time"
@ -20,53 +22,66 @@ func NewQuizFileStore(config *FileStoreConfig[*models.Quiz, *store.QuizStore]) (
return NewFileStore[*models.Quiz, *store.QuizStore](config, store.NewQuizStore())
}
func DefaultUnmarshalQuizFunc(s *store.QuizStore, filepath string, content []byte) (*models.Quiz, error) {
quiz, meta, err := models.MarkdownToQuiz(string(content))
func NewDefaultQuizFileStore() (*QuizFileStore, error) {
return NewQuizFileStore(
&FileStoreConfig[*models.Quiz, *store.QuizStore]{
FilePathConfig: FilePathConfig{GetDefaultQuizzesDir(), "quiz", ".md"},
IndexDirFunc: DefaultQuizIndexDirFunc,
},
)
}
func DefaultQuizIndexDirFunc(s *QuizFileStore) error {
files, err := os.ReadDir(s.Dir)
if err != nil {
return nil, err
return err
}
entityFiles := make([]fs.DirEntry, 0)
for _, file := range files {
filename := file.Name()
if !file.IsDir() && strings.HasSuffix(filename, s.FileSuffix) {
entityFiles = append(entityFiles, file)
}
}
for _, file := range entityFiles {
filename := file.Name()
fullPath := filepath.Join(s.Dir, filename)
content, err := os.ReadFile(fullPath)
if err != nil {
return err
}
var entity = new(models.Quiz)
err = entity.Unmarshal(content)
if err != nil {
return err
}
var errQuizAlreadyPresent *store.ErrQuizAlreadyPresent
q, err := s.Create(quiz)
mEntity, err := s.Create(entity)
if err != nil && !errors.As(err, &errQuizAlreadyPresent) {
return nil, err
return err
}
if meta == nil {
writeQuizHeader(filepath, &models.Meta{
ID: q.ID,
if entity.ID == "" {
writeQuizHeader(fullPath, &models.Meta{
ID: mEntity.ID,
CreatedAt: time.Now(),
})
}
return q, nil
}
func DefaultMarshalQuizFunc(s *store.QuizStore, filePath string, quiz *models.Quiz) error {
markdown, err := models.QuizToMarkdown(quiz)
if err != nil {
return err
}
file, err := os.Create(filePath)
if err != nil {
return err
}
defer file.Close()
markdownWithMetaHeader, err := addMetaHeaderToMarkdown(markdown, &quiz.Meta)
if err != nil {
return err
}
_, err = file.Write([]byte(markdownWithMetaHeader))
if err != nil {
return err
s.SetPath(mEntity, fullPath)
}
return nil
}
func writeQuizHeader(path string, meta *models.Meta) (*models.Meta, error) {

View file

@ -5,8 +5,6 @@ import (
"os"
"path/filepath"
"git.andreafazzi.eu/andrea/probo/models"
"git.andreafazzi.eu/andrea/probo/store"
"github.com/remogatto/prettytest"
)
@ -15,15 +13,7 @@ type quizTestSuite struct {
}
func (t *quizTestSuite) TestReadAll() {
filePathConfig := FilePathConfig{"testdata/quizzes", "quiz", ".md"}
store, err := NewQuizFileStore(
&FileStoreConfig[*models.Quiz, *store.QuizStore]{
FilePathConfig: filePathConfig,
IndexDirFunc: DefaultIndexDirFunc[*models.Quiz, *store.QuizStore],
UnmarshalFunc: DefaultUnmarshalQuizFunc,
MarshalFunc: DefaultMarshalQuizFunc,
},
)
store, err := NewDefaultQuizFileStore()
t.Nil(err)
if !t.Failed() {
@ -38,198 +28,174 @@ func (t *quizTestSuite) TestReadAll() {
),
)
files, _ := os.ReadDir(GetDefaultQuizzesDir())
t.Equal(5, len(files))
_, err = removeQuizHeader(filepath.Join(store.Dir, "quiz_5.md"))
}
}
func (t *quizTestSuite) TestCreate() {
filePathConfig := FilePathConfig{"testdata/quizzes", "quiz", ".md"}
store, err := NewQuizFileStore(
&FileStoreConfig[*models.Quiz, *store.QuizStore]{
FilePathConfig: filePathConfig,
IndexDirFunc: DefaultIndexDirFunc[*models.Quiz, *store.QuizStore],
UnmarshalFunc: DefaultUnmarshalQuizFunc,
MarshalFunc: DefaultMarshalQuizFunc,
NoIndexOnCreate: true,
},
)
t.Nil(err)
// func (t *quizTestSuite) TestCreate() {
// store, err := NewDefaultQuizFileStore()
// t.Nil(err)
if !t.Failed() {
quiz, err := store.Create(
&models.Quiz{
Question: &models.Question{Text: "Newly created question text with #tag1 #tag2."},
Answers: []*models.Answer{
{Text: "Answer 1"},
{Text: "Answer 2"},
{Text: "Answer 3"},
{Text: "Answer 4"},
},
CorrectPos: 0,
})
t.Nil(err)
t.Equal(2, len(quiz.Tags))
// if !t.Failed() {
// quiz, err := store.Create(
// &models.Quiz{
// Question: &models.Question{Text: "Newly created question text with #tag1 #tag2."},
// Answers: []*models.Answer{
// {Text: "Answer 1"},
// {Text: "Answer 2"},
// {Text: "Answer 3"},
// {Text: "Answer 4"},
// },
// CorrectPos: 0,
// })
// t.Nil(err)
// t.Equal(2, len(quiz.Tags))
if !t.Failed() {
path := store.GetPath(quiz)
t.True(path != "", "Path should not be empty.")
// if !t.Failed() {
// path := store.GetPath(quiz)
// t.True(path != "", "Path should not be empty.")
exists, err := os.Stat(path)
t.Nil(err)
// exists, err := os.Stat(path)
// t.Nil(err)
if !t.Failed() {
t.True(exists != nil, "The new quiz file was not created.")
// if !t.Failed() {
// t.True(exists != nil, "The new quiz file was not created.")
if !t.Failed() {
quizFromDisk, _, err := readQuizFromDisk(path)
defer os.Remove(path)
// if !t.Failed() {
// quizFromDisk, err := readQuizFromDisk(path)
// defer os.Remove(path)
quizFromDisk.Correct = quiz.Answers[0]
quizFromDisk.Tags = quiz.Tags
// quizFromDisk.Correct = quiz.Answers[0]
// quizFromDisk.Tags = quiz.Tags
t.Nil(err)
// t.Nil(err)
if !t.Failed() {
t.Equal(quizFromDisk.Question.Text, quiz.Question.Text)
for i, a := range quizFromDisk.Answers {
t.Equal(a.Text, quiz.Answers[i].Text)
}
for i, tag := range quizFromDisk.Tags {
t.Equal(tag.Name, quiz.Tags[i].Name)
}
}
}
}
// if !t.Failed() {
// t.Equal(quizFromDisk.Question.Text, quiz.Question.Text)
// for i, a := range quizFromDisk.Answers {
// t.Equal(a.Text, quiz.Answers[i].Text)
// }
// for i, tag := range quizFromDisk.Tags {
// t.Equal(tag.Name, quiz.Tags[i].Name)
// }
// }
// }
// }
}
}
}
// }
// }
// }
func (t *quizTestSuite) TestDelete() {
filePathConfig := FilePathConfig{"testdata/quizzes", "quiz", ".md"}
store, err := NewQuizFileStore(
&FileStoreConfig[*models.Quiz, *store.QuizStore]{
FilePathConfig: filePathConfig,
IndexDirFunc: DefaultIndexDirFunc[*models.Quiz, *store.QuizStore],
UnmarshalFunc: DefaultUnmarshalQuizFunc,
MarshalFunc: DefaultMarshalQuizFunc,
NoIndexOnCreate: true,
},
)
t.Nil(err)
// func (t *quizTestSuite) TestDelete() {
// store, err := NewDefaultQuizFileStore()
// t.Nil(err)
if !t.Failed() {
quiz, err := store.Create(
&models.Quiz{
Question: &models.Question{Text: "This quiz should be deleted."},
Answers: []*models.Answer{
{Text: "Answer 1"},
{Text: "Answer 2"},
{Text: "Answer 3"},
{Text: "Answer 4"},
},
CorrectPos: 0,
})
t.Nil(err)
if !t.Failed() {
path := store.GetPath(quiz)
_, err := store.Delete(quiz.ID)
t.Nil(err, fmt.Sprintf("Quiz should be deleted without errors: %v", err))
if !t.Failed() {
_, err := os.Stat(path)
t.Not(t.Nil(err))
// if !t.Failed() {
// quiz, err := store.Create(
// &models.Quiz{
// Question: &models.Question{Text: "This quiz should be deleted."},
// Answers: []*models.Answer{
// {Text: "Answer 1"},
// {Text: "Answer 2"},
// {Text: "Answer 3"},
// {Text: "Answer 4"},
// },
// CorrectPos: 0,
// })
// t.Nil(err)
// if !t.Failed() {
// path := store.GetPath(quiz)
// _, err := store.Delete(quiz.ID)
// t.Nil(err, fmt.Sprintf("Quiz should be deleted without errors: %v", err))
// if !t.Failed() {
// _, err := os.Stat(path)
// t.Not(t.Nil(err))
}
// }
}
}
}
// }
// }
// }
func (t *quizTestSuite) TestUpdate() {
filePathConfig := FilePathConfig{"testdata/quizzes", "quiz", ".md"}
store, err := NewQuizFileStore(
&FileStoreConfig[*models.Quiz, *store.QuizStore]{
FilePathConfig: filePathConfig,
IndexDirFunc: DefaultIndexDirFunc[*models.Quiz, *store.QuizStore],
UnmarshalFunc: DefaultUnmarshalQuizFunc,
MarshalFunc: DefaultMarshalQuizFunc,
NoIndexOnCreate: true,
},
)
t.Nil(err)
// func (t *quizTestSuite) TestUpdate() {
// store, err := NewDefaultQuizFileStore()
// t.Nil(err)
if !t.Failed() {
quiz, err := store.Create(
&models.Quiz{
Question: &models.Question{Text: "Newly created question text with #tag1 #tag2."},
Answers: []*models.Answer{
{Text: "Answer 1"},
{Text: "Answer 2"},
{Text: "Answer 3"},
{Text: "Answer 4"},
},
CorrectPos: 0,
})
t.Nil(err)
// if !t.Failed() {
// quiz, err := store.Create(
// &models.Quiz{
// Question: &models.Question{Text: "Newly created question text with #tag1 #tag2."},
// Answers: []*models.Answer{
// {Text: "Answer 1"},
// {Text: "Answer 2"},
// {Text: "Answer 3"},
// {Text: "Answer 4"},
// },
// CorrectPos: 0,
// })
// t.Nil(err)
_, err = store.Update(&models.Quiz{
Question: &models.Question{Text: "Newly created question text with #tag1 #tag2 #tag3."},
Answers: []*models.Answer{
{Text: "Answer 1"},
{Text: "Answer 2"},
{Text: "Answer 3"},
{Text: "Answer 4"},
},
CorrectPos: 1,
}, quiz.ID)
// _, err = store.Update(&models.Quiz{
// Question: &models.Question{Text: "Newly created question text with #tag1 #tag2 #tag3."},
// Answers: []*models.Answer{
// {Text: "Answer 1"},
// {Text: "Answer 2"},
// {Text: "Answer 3"},
// {Text: "Answer 4"},
// },
// CorrectPos: 1,
// }, quiz.ID)
t.Nil(err)
// t.Nil(err)
updatedQuizFromMemory, err := store.Read(quiz.ID)
t.Equal(len(updatedQuizFromMemory.Tags), 3)
t.Equal("Answer 2", updatedQuizFromMemory.Correct.Text)
// updatedQuizFromMemory, err := store.Read(quiz.ID)
// t.Equal(len(updatedQuizFromMemory.Tags), 3)
// t.Equal("Answer 2", updatedQuizFromMemory.Correct.Text)
defer os.Remove(store.GetPath(quiz))
// defer os.Remove(store.GetPath(quiz))
}
}
// }
// }
func (t *quizTestSuite) TestAutowriteHeader() {
filePathConfig := FilePathConfig{"testdata/quizzes", "quiz", ".md"}
store, err := NewQuizFileStore(
&FileStoreConfig[*models.Quiz, *store.QuizStore]{
FilePathConfig: filePathConfig,
IndexDirFunc: DefaultIndexDirFunc[*models.Quiz, *store.QuizStore],
UnmarshalFunc: DefaultUnmarshalQuizFunc,
MarshalFunc: DefaultMarshalQuizFunc,
},
)
t.Nil(err)
// func (t *quizTestSuite) TestAutowriteHeader() {
// store, err := NewDefaultQuizFileStore()
// t.Nil(err)
if !t.Failed() {
// if !t.Failed() {
meta, err := readQuizHeader(filepath.Join(store.Dir, "quiz_5.md"))
t.Nil(err)
// meta, err := readQuizHeader(filepath.Join(store.Dir, "quiz_5.md"))
// t.Nil(err)
if !t.Failed() {
t.Not(t.Nil(meta))
// if !t.Failed() {
// t.Not(t.Nil(meta))
if !t.Failed() {
t.True(meta.ID != "", "ID should not be empty")
// if !t.Failed() {
// t.True(meta.ID != "", "ID should not be empty")
if !t.Failed() {
_, err = removeQuizHeader(filepath.Join(store.Dir, "quiz_5.md"))
t.True(err == nil)
}
}
}
}
}
// if !t.Failed() {
// _, err = removeQuizHeader(filepath.Join(store.Dir, "quiz_5.md"))
// t.True(err == nil)
// }
// }
// }
// }
// }
func readQuizFromDisk(path string) (*models.Quiz, *models.Meta, error) {
content, err := os.ReadFile(path)
if err != nil {
return nil, nil, err
}
return models.MarkdownToQuiz(string(content))
}
// func readQuizFromDisk(path string) (*models.Quiz, error) {
// content, err := os.ReadFile(path)
// if err != nil {
// return nil, err
// }
// result := new(models.Quiz)
// err = result.Unmarshal(content)
// if err != nil {
// return nil, err
// }
// return result, nil
// }