package file import ( "fmt" "os" "reflect" "testing" "git.andreafazzi.eu/andrea/probo/client" "git.andreafazzi.eu/andrea/probo/hasher/sha256" "git.andreafazzi.eu/andrea/probo/models" "git.andreafazzi.eu/andrea/probo/store/memory" "github.com/remogatto/prettytest" ) type testSuite struct { prettytest.Suite } func TestRunner(t *testing.T) { prettytest.Run( t, new(testSuite), ) } func (t *testSuite) TestQuizFromMarkdown() { markdown := `Question text (1). Question text (2). Question text (3). * Answer 1 * Answer 2 * Answer 3 * Answer 4` expectedQuiz := &client.Quiz{ Question: &client.Question{Text: "Question text (1).\n\nQuestion text (2).\n\nQuestion text (3)."}, Answers: []*client.Answer{ {Text: "Answer 1", Correct: true}, {Text: "Answer 2", Correct: false}, {Text: "Answer 3", Correct: false}, {Text: "Answer 4", Correct: false}, }, } quiz, err := QuizFromMarkdown(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)) } } func (t *testSuite) TestReadAllQuizzes() { store, err := NewFileProboCollectorStore("./testdata/quizzes") t.True(err == nil, fmt.Sprintf("A file store should be initialized without problems but an error occurred: %v", err)) if !t.Failed() { result, err := store.ReadAllQuizzes() t.True(err == nil, fmt.Sprintf("Quizzes should be returned without errors: %v", err)) if !t.Failed() { t.Equal( 2, len(result), fmt.Sprintf("The store contains 3 files but only 2 should be parsed (duplicated quiz). Total of parsed quizzes are instead %v", len(result)), ) } } } func (t *testSuite) TestMarkdownFromQuiz() { store := memory.NewMemoryProboCollectorStore(sha256.NewDefault256Hasher(sha256.DefaultSHA256HashingFn)) quiz, err := store.CreateQuiz( &client.CreateUpdateQuizRequest{ Quiz: &client.Quiz{ Question: &client.Question{Text: "Newly created question text."}, Answers: []*client.Answer{ {Text: "Answer 1", Correct: true}, {Text: "Answer 2", Correct: false}, {Text: "Answer 3", Correct: false}, {Text: "Answer 4", Correct: false}, }, }, }) md, err := MarkdownFromQuiz(quiz) t.Nil(err, "Conversion to markdown should not raise an error") if !t.Failed() { t.Equal(`Newly created question text. * Answer 1 * Answer 2 * Answer 3 * Answer 4 `, md) } } func (t *testSuite) TestCreateQuiz() { dirname := "./testdata/quizzes" store, err := NewFileProboCollectorStore(dirname) t.True(err == nil, fmt.Sprintf("A file store should be initialized without problems but an error occurred: %v", err)) if !t.Failed() { clientQuiz := &client.Quiz{ Question: &client.Question{Text: "Newly created question text."}, Answers: []*client.Answer{ {Text: "Answer 1", Correct: true}, {Text: "Answer 2", Correct: false}, {Text: "Answer 3", Correct: false}, {Text: "Answer 4", Correct: false}, }, } quiz, err := store.CreateQuiz( &client.CreateUpdateQuizRequest{ Quiz: clientQuiz, }, ) t.Nil(err, fmt.Sprintf("An error was raised when saving the quiz on disk: %v", err)) if !t.Failed() { path, err := store.GetPath(quiz) t.Nil(err, "GetPath should not raise an error.") if !t.Failed() { exists, err := os.Stat(path) t.Nil(err, "Stat should not return an error") if !t.Failed() { t.True(exists != nil, "The new quiz file was not created.") if !t.Failed() { quizFromDisk, err := readQuizFromDisk(path) t.Nil(err, "Quiz should be read from disk without errors.") if !t.Failed() { t.True(reflect.DeepEqual(quizFromDisk, clientQuiz), "Quiz read from disk and stored in memory should be equal.") err := os.Remove(path) t.Nil(err, "Test file should be removed without errors.") } } } } } } } func (t *testSuite) TestUpdateQuiz() { dirname := "./testdata/quizzes" store, err := NewFileProboCollectorStore(dirname) t.True(err == nil, fmt.Sprintf("A file store should be initialized without problems but an error occurred: %v", err)) if !t.Failed() { quiz, err := createQuizOnDisk(store, &client.CreateUpdateQuizRequest{ Quiz: &client.Quiz{ Question: &client.Question{Text: "Newly created question text."}, Answers: []*client.Answer{ {Text: "Answer 1", Correct: true}, {Text: "Answer 2", Correct: false}, {Text: "Answer 3", Correct: false}, {Text: "Answer 4", Correct: false}, }, }, }) t.Nil(err, "The quiz to be updated should be created without issue") if !t.Failed() { clientQuiz := &client.Quiz{ Question: &client.Question{Text: "Newly created question text."}, Answers: []*client.Answer{ {Text: "Answer 1", Correct: true}, {Text: "Answer 2", Correct: false}, {Text: "Answer 3", Correct: false}, {Text: "Answer 4", Correct: false}, }, } updatedQuiz, err := store.UpdateQuiz( &client.CreateUpdateQuizRequest{ Quiz: clientQuiz, }, quiz.ID) t.Nil(err, fmt.Sprintf("Quiz should be updated without errors: %v", err)) // t.Equal(updatedQuiz.ID, quiz.ID, "Quiz ID should remain the same") if !t.Failed() { path, err := store.GetPath(updatedQuiz) if !t.Failed() { t.Nil(err, "GetPath should not raise an error.") if !t.Failed() { quizFromDisk, err := readQuizFromDisk(path) t.Nil(err, "Quiz should be read from disk without errors.") if !t.Failed() { t.True(reflect.DeepEqual(clientQuiz, quizFromDisk), "Quiz should be updated.") err := os.Remove(path) t.Nil(err, "Stat should not return an error") } } } } } } } func createQuizOnDisk(store *FileProboCollectorStore, req *client.CreateUpdateQuizRequest) (*models.Quiz, error) { return store.CreateQuiz(req) } func readQuizFromDisk(path string) (*client.Quiz, error) { content, err := os.ReadFile(path) if err != nil { return nil, err } return QuizFromMarkdown(string(content)) } func testsAreEqual(got, want []*models.Quiz) bool { return reflect.DeepEqual(got, want) }