Adds a full flashcards system: FSRS-based scheduling, cloze/basic card types, CSV import/export, media storage, and study UI, wired into navigation and the dashboard alongside existing question flows.
76 lines
2.1 KiB
C#
76 lines
2.1 KiB
C#
using QuestionsApi.Services.Flashcards;
|
|
using Xunit;
|
|
|
|
namespace QuestionsApi.Tests;
|
|
|
|
public sealed class FlashcardCsvTests
|
|
{
|
|
[Fact]
|
|
public void ParseRows_HandlesQuotedMultilineFieldsAndEmbeddedCommas()
|
|
{
|
|
var csv = "stable_id,deck,type,prompt,answer,extra,tags,source_question_external_id\n"
|
|
+ "abc-1,Cardio,basic,\"What is the first line,\nsecond line?\",\"Answer, with comma\",,tag1;tag2,q-1\n";
|
|
|
|
var rows = FlashcardCsv.ParseRows(csv);
|
|
|
|
Assert.Equal(2, rows.Count);
|
|
var data = rows[1];
|
|
Assert.Equal("abc-1", data[0]);
|
|
Assert.Equal("What is the first line,\nsecond line?", data[3]);
|
|
Assert.Equal("Answer, with comma", data[4]);
|
|
Assert.Equal("tag1;tag2", data[6]);
|
|
}
|
|
|
|
[Fact]
|
|
public void ParseRows_HandlesEscapedDoubleQuotes()
|
|
{
|
|
var csv = "a,b\n\"she said \"\"hi\"\"\",plain\n";
|
|
|
|
var rows = FlashcardCsv.ParseRows(csv);
|
|
|
|
Assert.Equal("she said \"hi\"", rows[1][0]);
|
|
Assert.Equal("plain", rows[1][1]);
|
|
}
|
|
|
|
[Fact]
|
|
public void ParseRows_SupportsUnicodeContent()
|
|
{
|
|
var csv = "a,b\néè中文,\U0001F600\n";
|
|
|
|
var rows = FlashcardCsv.ParseRows(csv);
|
|
|
|
Assert.Equal("éè中文", rows[1][0]);
|
|
Assert.Equal("😀", rows[1][1]);
|
|
}
|
|
|
|
[Fact]
|
|
public void ParseRows_HandlesFileWithoutTrailingNewline()
|
|
{
|
|
var csv = "a,b\n1,2";
|
|
|
|
var rows = FlashcardCsv.ParseRows(csv);
|
|
|
|
Assert.Equal(2, rows.Count);
|
|
Assert.Equal(["1", "2"], rows[1]);
|
|
}
|
|
|
|
[Fact]
|
|
public void WriteRow_QuotesFieldsContainingSpecialCharacters()
|
|
{
|
|
var row = FlashcardCsv.WriteRow(["plain", "has,comma", "has\"quote", "has\nnewline"]);
|
|
|
|
Assert.Equal("plain,\"has,comma\",\"has\"\"quote\",\"has\nnewline\"", row);
|
|
}
|
|
|
|
[Fact]
|
|
public void WriteThenParse_RoundTrips()
|
|
{
|
|
var original = new[] { "id-1", "Deck, Name", "basic", "prompt with \"quotes\" and\nnewline", "answer", "", "a;b", "q-1" };
|
|
var line = FlashcardCsv.WriteRow(original);
|
|
|
|
var rows = FlashcardCsv.ParseRows("header\n" + line + "\n");
|
|
|
|
Assert.Equal(original, rows[1]);
|
|
}
|
|
}
|