101 lines
3.7 KiB
Go
101 lines
3.7 KiB
Go
package quizzes_test
|
|
|
|
import (
|
|
"bytes"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"git.golem15.com/golem15/sm-quizzes-plugin/models"
|
|
"git.golem15.com/golem15/summercms/modules/bonfire"
|
|
"git.golem15.com/golem15/summercms/modules/pact"
|
|
)
|
|
|
|
func TestImportCommand(t *testing.T) {
|
|
_, plugins, gdb := migrated(t)
|
|
cmds := quizzesPlugin(t, plugins).(pact.HasCommands).Commands()
|
|
run := func(args ...string) (string, error) {
|
|
var out bytes.Buffer
|
|
err := bonfire.Call(t.Context(), cmds, "quizzes:import", args, &out)
|
|
return out.String(), err
|
|
}
|
|
|
|
out, err := run("testdata/quiz.json")
|
|
if err != nil {
|
|
t.Fatalf("import: %v\n%s", err, out)
|
|
}
|
|
if !strings.Contains(out, "created quiz bezpieczenstwo-pojecia") || !strings.Contains(out, "3 questions, 5 answers") {
|
|
t.Errorf("output = %q", out)
|
|
}
|
|
var quiz models.Quiz
|
|
must(t, gdb.Preload("Questions.Answers").Where("slug = ?", "bezpieczenstwo-pojecia").Take(&quiz).Error)
|
|
if !quiz.IsPublished || quiz.PassingScore != 60 || quiz.RoundSize == nil || *quiz.RoundSize != 5 || *quiz.Context != "acme.courses:course:12" {
|
|
t.Errorf("quiz = %+v", quiz)
|
|
}
|
|
if len(quiz.Questions) != 3 {
|
|
t.Fatalf("questions = %d", len(quiz.Questions))
|
|
}
|
|
byOrder := map[int]models.Question{}
|
|
for _, q := range quiz.Questions {
|
|
byOrder[q.SortOrder] = q
|
|
}
|
|
if q := byOrder[1]; q.Type != models.TypeSelfCheck || *q.Category != "Teoria" || q.AnswerText == nil || q.Points != 1 {
|
|
t.Errorf("first question = %+v", q)
|
|
}
|
|
if q := byOrder[3]; q.Points != 2 || len(q.Answers) != 3 || *q.Category != "Globalizacja" {
|
|
t.Errorf("third question = %+v", q)
|
|
}
|
|
|
|
// Without --replace an existing slug is refused and nothing changes.
|
|
if _, err := run("testdata/quiz.json"); err == nil || !strings.Contains(err.Error(), "--replace") {
|
|
t.Errorf("second import without --replace = %v", err)
|
|
}
|
|
|
|
// --replace recreates the questions; attempt answers to the old ones go
|
|
// with them.
|
|
u, _ := newUser(t, gdb, "ala@example.com")
|
|
a := models.Attempt{QuizID: quiz.ID, UserID: u.ID, StartedAt: time.Now()}
|
|
must(t, gdb.Create(&a).Error)
|
|
must(t, gdb.Create(&models.AttemptAnswer{AttemptID: a.ID, QuestionID: byOrder[1].ID}).Error)
|
|
|
|
changed := filepath.Join(t.TempDir(), "quiz.json")
|
|
raw, _ := os.ReadFile("testdata/quiz.json")
|
|
raw = bytes.Replace(raw, []byte(`"passing_score": 60`), []byte(`"slug": "bezpieczenstwo-pojecia", "passing_score": 70`), 1)
|
|
raw = bytes.Replace(raw, []byte(`"Czym jest odporność społeczna?"`), []byte(`"Czym jest obrona totalna?"`), 1)
|
|
must(t, os.WriteFile(changed, raw, 0o644))
|
|
out, err = run(changed, "--replace")
|
|
if err != nil || !strings.Contains(out, "replaced quiz bezpieczenstwo-pojecia (id ") {
|
|
t.Fatalf("replace = %v %q", err, out)
|
|
}
|
|
var again models.Quiz
|
|
must(t, gdb.Preload("Questions").Where("slug = ?", "bezpieczenstwo-pojecia").Take(&again).Error)
|
|
if again.ID != quiz.ID || again.PassingScore != 70 || len(again.Questions) != 3 {
|
|
t.Errorf("replaced quiz = %+v", again)
|
|
}
|
|
var n int64
|
|
must(t, gdb.Model(&models.Question{}).Where("text = ?", "Czym jest obrona totalna?").Count(&n).Error)
|
|
if n != 1 {
|
|
t.Errorf("new question rows = %d", n)
|
|
}
|
|
must(t, gdb.Model(&models.AttemptAnswer{}).Count(&n).Error)
|
|
if n != 0 {
|
|
t.Errorf("attempt answers after replace = %d", n)
|
|
}
|
|
must(t, gdb.Model(&models.Attempt{}).Count(&n).Error)
|
|
if n != 1 {
|
|
t.Errorf("attempts after replace = %d, want the attempt kept", n)
|
|
}
|
|
|
|
// Errors.
|
|
if _, err := run("testdata/missing.json"); err == nil {
|
|
t.Error("a missing file imported")
|
|
}
|
|
bad := filepath.Join(t.TempDir(), "bad.json")
|
|
must(t, os.WriteFile(bad, []byte(`{"title":"X","questions":[]}`), 0o644))
|
|
if _, err := run(bad); err == nil || !strings.Contains(err.Error(), "questions must not be empty") {
|
|
t.Errorf("invalid file = %v", err)
|
|
}
|
|
}
|