mirror of
https://github.com/kjanat/articulate-parser.git
synced 2026-01-16 14:22:10 +01:00
chore: Apply modern Go idioms and perform code cleanup
This commit introduces a series of small refactorings and style fixes across the codebase to improve consistency and leverage modern Go features.
Key changes include:
- Adopting the Go 1.22 `reflect.TypeFor` generic function.
- Replacing `interface{}` with the `any` type alias for better readability.
- Using the explicit `http.NoBody` constant for HTTP requests.
- Updating octal literals for file permissions to the `0o` prefix syntax.
- Standardizing comment formatting and fixing minor typos.
- Removing redundant blank lines and organizing imports.
This commit is contained in:
@ -8,11 +8,12 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/fumiama/go-docx"
|
||||
"golang.org/x/text/cases"
|
||||
"golang.org/x/text/language"
|
||||
|
||||
"github.com/kjanat/articulate-parser/internal/interfaces"
|
||||
"github.com/kjanat/articulate-parser/internal/models"
|
||||
"github.com/kjanat/articulate-parser/internal/services"
|
||||
"golang.org/x/text/cases"
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
// DocxExporter implements the Exporter interface for DOCX format.
|
||||
|
||||
@ -90,7 +90,6 @@ func TestDocxExporter_Export_AddDocxExtension(t *testing.T) {
|
||||
|
||||
err := exporter.Export(testCourse, outputPath)
|
||||
if err != nil {
|
||||
|
||||
t.Fatalf("Export failed: %v", err)
|
||||
}
|
||||
|
||||
@ -155,7 +154,6 @@ func TestDocxExporter_ExportLesson(t *testing.T) {
|
||||
|
||||
err := exporter.Export(course, outputPath)
|
||||
if err != nil {
|
||||
|
||||
t.Fatalf("Export failed: %v", err)
|
||||
}
|
||||
|
||||
@ -222,7 +220,6 @@ func TestDocxExporter_ExportItem(t *testing.T) {
|
||||
|
||||
err := exporter.Export(course, outputPath)
|
||||
if err != nil {
|
||||
|
||||
t.Fatalf("Export failed: %v", err)
|
||||
}
|
||||
|
||||
@ -276,7 +273,6 @@ func TestDocxExporter_ExportSubItem(t *testing.T) {
|
||||
|
||||
err := exporter.Export(course, outputPath)
|
||||
if err != nil {
|
||||
|
||||
t.Fatalf("Export failed: %v", err)
|
||||
}
|
||||
|
||||
@ -409,7 +405,6 @@ func TestDocxExporter_ComplexCourse(t *testing.T) {
|
||||
// Export course
|
||||
err := exporter.Export(course, outputPath)
|
||||
if err != nil {
|
||||
|
||||
t.Fatalf("Export failed: %v", err)
|
||||
}
|
||||
|
||||
@ -444,7 +439,6 @@ func TestDocxExporter_EmptyCourse(t *testing.T) {
|
||||
|
||||
err := exporter.Export(course, outputPath)
|
||||
if err != nil {
|
||||
|
||||
t.Fatalf("Export failed: %v", err)
|
||||
}
|
||||
|
||||
@ -493,7 +487,6 @@ func TestDocxExporter_HTMLCleaning(t *testing.T) {
|
||||
|
||||
err := exporter.Export(course, outputPath)
|
||||
if err != nil {
|
||||
|
||||
t.Fatalf("Export failed: %v", err)
|
||||
}
|
||||
|
||||
@ -516,7 +509,6 @@ func TestDocxExporter_ExistingDocxExtension(t *testing.T) {
|
||||
|
||||
err := exporter.Export(testCourse, outputPath)
|
||||
if err != nil {
|
||||
|
||||
t.Fatalf("Export failed: %v", err)
|
||||
}
|
||||
|
||||
@ -552,7 +544,6 @@ func TestDocxExporter_CaseInsensitiveExtension(t *testing.T) {
|
||||
|
||||
err := exporter.Export(testCourse, outputPath)
|
||||
if err != nil {
|
||||
|
||||
t.Fatalf("Export failed for case %d (%s): %v", i, testCase, err)
|
||||
}
|
||||
|
||||
|
||||
@ -164,7 +164,6 @@ func TestFactory_CreateExporter_CaseInsensitive(t *testing.T) {
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.format, func(t *testing.T) {
|
||||
exporter, err := factory.CreateExporter(tc.format)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error for format '%s': %v", tc.format, err)
|
||||
}
|
||||
|
||||
@ -9,11 +9,12 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/text/cases"
|
||||
"golang.org/x/text/language"
|
||||
|
||||
"github.com/kjanat/articulate-parser/internal/interfaces"
|
||||
"github.com/kjanat/articulate-parser/internal/models"
|
||||
"github.com/kjanat/articulate-parser/internal/services"
|
||||
"golang.org/x/text/cases"
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
// HTMLExporter implements the Exporter interface for HTML format.
|
||||
@ -111,7 +112,7 @@ func (e *HTMLExporter) Export(course *models.Course, outputPath string) error {
|
||||
buf.WriteString("</html>\n")
|
||||
|
||||
// #nosec G306 - 0644 is appropriate for export files that should be readable by others
|
||||
return os.WriteFile(outputPath, buf.Bytes(), 0644)
|
||||
return os.WriteFile(outputPath, buf.Bytes(), 0o644)
|
||||
}
|
||||
|
||||
// SupportedFormat returns the format name this exporter supports
|
||||
@ -123,7 +124,7 @@ func (e *HTMLExporter) SupportedFormat() string {
|
||||
return "html"
|
||||
}
|
||||
|
||||
// getDefaultCSS returns basic CSS styling for the HTML document
|
||||
// getDefaultCSS returns basic CSS styling for the HTML document.
|
||||
func (e *HTMLExporter) getDefaultCSS() string {
|
||||
return `
|
||||
body {
|
||||
@ -330,7 +331,7 @@ func (e *HTMLExporter) processItemToHTML(buf *bytes.Buffer, item models.Item) {
|
||||
}
|
||||
}
|
||||
|
||||
// processTextItem handles text content with headings and paragraphs
|
||||
// processTextItem handles text content with headings and paragraphs.
|
||||
func (e *HTMLExporter) processTextItem(buf *bytes.Buffer, item models.Item) {
|
||||
buf.WriteString(" <div class=\"item text-item\">\n")
|
||||
buf.WriteString(" <h4>Text Content</h4>\n")
|
||||
@ -345,7 +346,7 @@ func (e *HTMLExporter) processTextItem(buf *bytes.Buffer, item models.Item) {
|
||||
buf.WriteString(" </div>\n\n")
|
||||
}
|
||||
|
||||
// processListItem handles list content
|
||||
// processListItem handles list content.
|
||||
func (e *HTMLExporter) processListItem(buf *bytes.Buffer, item models.Item) {
|
||||
buf.WriteString(" <div class=\"item list-item\">\n")
|
||||
buf.WriteString(" <h4>List</h4>\n")
|
||||
@ -360,7 +361,7 @@ func (e *HTMLExporter) processListItem(buf *bytes.Buffer, item models.Item) {
|
||||
buf.WriteString(" </div>\n\n")
|
||||
}
|
||||
|
||||
// processKnowledgeCheckItem handles quiz questions and answers
|
||||
// processKnowledgeCheckItem handles quiz questions and answers.
|
||||
func (e *HTMLExporter) processKnowledgeCheckItem(buf *bytes.Buffer, item models.Item) {
|
||||
buf.WriteString(" <div class=\"item knowledge-check\">\n")
|
||||
buf.WriteString(" <h4>Knowledge Check</h4>\n")
|
||||
@ -378,7 +379,7 @@ func (e *HTMLExporter) processKnowledgeCheckItem(buf *bytes.Buffer, item models.
|
||||
buf.WriteString(" </div>\n\n")
|
||||
}
|
||||
|
||||
// processMultimediaItem handles multimedia content like videos
|
||||
// processMultimediaItem handles multimedia content like videos.
|
||||
func (e *HTMLExporter) processMultimediaItem(buf *bytes.Buffer, item models.Item) {
|
||||
buf.WriteString(" <div class=\"item multimedia-item\">\n")
|
||||
buf.WriteString(" <h4>Media Content</h4>\n")
|
||||
@ -403,7 +404,7 @@ func (e *HTMLExporter) processMultimediaItem(buf *bytes.Buffer, item models.Item
|
||||
buf.WriteString(" </div>\n\n")
|
||||
}
|
||||
|
||||
// processImageItem handles image content
|
||||
// processImageItem handles image content.
|
||||
func (e *HTMLExporter) processImageItem(buf *bytes.Buffer, item models.Item) {
|
||||
buf.WriteString(" <div class=\"item multimedia-item\">\n")
|
||||
buf.WriteString(" <h4>Image</h4>\n")
|
||||
@ -420,7 +421,7 @@ func (e *HTMLExporter) processImageItem(buf *bytes.Buffer, item models.Item) {
|
||||
buf.WriteString(" </div>\n\n")
|
||||
}
|
||||
|
||||
// processInteractiveItem handles interactive content
|
||||
// processInteractiveItem handles interactive content.
|
||||
func (e *HTMLExporter) processInteractiveItem(buf *bytes.Buffer, item models.Item) {
|
||||
buf.WriteString(" <div class=\"item interactive-item\">\n")
|
||||
buf.WriteString(" <h4>Interactive Content</h4>\n")
|
||||
@ -435,12 +436,12 @@ func (e *HTMLExporter) processInteractiveItem(buf *bytes.Buffer, item models.Ite
|
||||
buf.WriteString(" </div>\n\n")
|
||||
}
|
||||
|
||||
// processDividerItem handles divider elements
|
||||
// processDividerItem handles divider elements.
|
||||
func (e *HTMLExporter) processDividerItem(buf *bytes.Buffer) {
|
||||
buf.WriteString(" <hr>\n\n")
|
||||
}
|
||||
|
||||
// processUnknownItem handles unknown or unsupported item types
|
||||
// processUnknownItem handles unknown or unsupported item types.
|
||||
func (e *HTMLExporter) processUnknownItem(buf *bytes.Buffer, item models.Item) {
|
||||
if len(item.Items) > 0 {
|
||||
buf.WriteString(" <div class=\"item unknown-item\">\n")
|
||||
@ -453,7 +454,7 @@ func (e *HTMLExporter) processUnknownItem(buf *bytes.Buffer, item models.Item) {
|
||||
}
|
||||
}
|
||||
|
||||
// processGenericSubItem processes sub-items for unknown types
|
||||
// processGenericSubItem processes sub-items for unknown types.
|
||||
func (e *HTMLExporter) processGenericSubItem(buf *bytes.Buffer, subItem models.SubItem) {
|
||||
if subItem.Title != "" {
|
||||
fmt.Fprintf(buf, " <p><strong>%s</strong></p>\n", subItem.Title)
|
||||
@ -463,7 +464,7 @@ func (e *HTMLExporter) processGenericSubItem(buf *bytes.Buffer, subItem models.S
|
||||
}
|
||||
}
|
||||
|
||||
// processAnswers processes answer choices for quiz questions
|
||||
// processAnswers processes answer choices for quiz questions.
|
||||
func (e *HTMLExporter) processAnswers(buf *bytes.Buffer, answers []models.Answer) {
|
||||
buf.WriteString(" <div class=\"answers\">\n")
|
||||
buf.WriteString(" <h5>Answers:</h5>\n")
|
||||
|
||||
@ -8,11 +8,12 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/text/cases"
|
||||
"golang.org/x/text/language"
|
||||
|
||||
"github.com/kjanat/articulate-parser/internal/interfaces"
|
||||
"github.com/kjanat/articulate-parser/internal/models"
|
||||
"github.com/kjanat/articulate-parser/internal/services"
|
||||
"golang.org/x/text/cases"
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
// MarkdownExporter implements the Exporter interface for Markdown format.
|
||||
@ -81,7 +82,7 @@ func (e *MarkdownExporter) Export(course *models.Course, outputPath string) erro
|
||||
}
|
||||
|
||||
// #nosec G306 - 0644 is appropriate for export files that should be readable by others
|
||||
return os.WriteFile(outputPath, buf.Bytes(), 0644)
|
||||
return os.WriteFile(outputPath, buf.Bytes(), 0o644)
|
||||
}
|
||||
|
||||
// SupportedFormat returns "markdown".
|
||||
@ -114,7 +115,7 @@ func (e *MarkdownExporter) processItemToMarkdown(buf *bytes.Buffer, item models.
|
||||
}
|
||||
}
|
||||
|
||||
// processTextItem handles text content with headings and paragraphs
|
||||
// processTextItem handles text content with headings and paragraphs.
|
||||
func (e *MarkdownExporter) processTextItem(buf *bytes.Buffer, item models.Item, headingPrefix string) {
|
||||
for _, subItem := range item.Items {
|
||||
if subItem.Heading != "" {
|
||||
@ -132,7 +133,7 @@ func (e *MarkdownExporter) processTextItem(buf *bytes.Buffer, item models.Item,
|
||||
}
|
||||
}
|
||||
|
||||
// processListItem handles list items with bullet points
|
||||
// processListItem handles list items with bullet points.
|
||||
func (e *MarkdownExporter) processListItem(buf *bytes.Buffer, item models.Item) {
|
||||
for _, subItem := range item.Items {
|
||||
if subItem.Paragraph != "" {
|
||||
@ -145,7 +146,7 @@ func (e *MarkdownExporter) processListItem(buf *bytes.Buffer, item models.Item)
|
||||
buf.WriteString("\n")
|
||||
}
|
||||
|
||||
// processMultimediaItem handles multimedia content including videos and images
|
||||
// processMultimediaItem handles multimedia content including videos and images.
|
||||
func (e *MarkdownExporter) processMultimediaItem(buf *bytes.Buffer, item models.Item, headingPrefix string) {
|
||||
fmt.Fprintf(buf, "%s Media Content\n\n", headingPrefix)
|
||||
for _, subItem := range item.Items {
|
||||
@ -154,7 +155,7 @@ func (e *MarkdownExporter) processMultimediaItem(buf *bytes.Buffer, item models.
|
||||
buf.WriteString("\n")
|
||||
}
|
||||
|
||||
// processMediaSubItem processes individual media items (video/image)
|
||||
// processMediaSubItem processes individual media items (video/image).
|
||||
func (e *MarkdownExporter) processMediaSubItem(buf *bytes.Buffer, subItem models.SubItem) {
|
||||
if subItem.Media != nil {
|
||||
e.processVideoMedia(buf, subItem.Media)
|
||||
@ -166,7 +167,7 @@ func (e *MarkdownExporter) processMediaSubItem(buf *bytes.Buffer, subItem models
|
||||
}
|
||||
}
|
||||
|
||||
// processVideoMedia processes video media content
|
||||
// processVideoMedia processes video media content.
|
||||
func (e *MarkdownExporter) processVideoMedia(buf *bytes.Buffer, media *models.Media) {
|
||||
if media.Video != nil {
|
||||
fmt.Fprintf(buf, "**Video**: %s\n", media.Video.OriginalUrl)
|
||||
@ -176,14 +177,14 @@ func (e *MarkdownExporter) processVideoMedia(buf *bytes.Buffer, media *models.Me
|
||||
}
|
||||
}
|
||||
|
||||
// processImageMedia processes image media content
|
||||
// processImageMedia processes image media content.
|
||||
func (e *MarkdownExporter) processImageMedia(buf *bytes.Buffer, media *models.Media) {
|
||||
if media.Image != nil {
|
||||
fmt.Fprintf(buf, "**Image**: %s\n", media.Image.OriginalUrl)
|
||||
}
|
||||
}
|
||||
|
||||
// processImageItem handles standalone image items
|
||||
// processImageItem handles standalone image items.
|
||||
func (e *MarkdownExporter) processImageItem(buf *bytes.Buffer, item models.Item, headingPrefix string) {
|
||||
fmt.Fprintf(buf, "%s Image\n\n", headingPrefix)
|
||||
for _, subItem := range item.Items {
|
||||
@ -198,7 +199,7 @@ func (e *MarkdownExporter) processImageItem(buf *bytes.Buffer, item models.Item,
|
||||
buf.WriteString("\n")
|
||||
}
|
||||
|
||||
// processKnowledgeCheckItem handles quiz questions and knowledge checks
|
||||
// processKnowledgeCheckItem handles quiz questions and knowledge checks.
|
||||
func (e *MarkdownExporter) processKnowledgeCheckItem(buf *bytes.Buffer, item models.Item, headingPrefix string) {
|
||||
fmt.Fprintf(buf, "%s Knowledge Check\n\n", headingPrefix)
|
||||
for _, subItem := range item.Items {
|
||||
@ -207,7 +208,7 @@ func (e *MarkdownExporter) processKnowledgeCheckItem(buf *bytes.Buffer, item mod
|
||||
buf.WriteString("\n")
|
||||
}
|
||||
|
||||
// processQuestionSubItem processes individual question items
|
||||
// processQuestionSubItem processes individual question items.
|
||||
func (e *MarkdownExporter) processQuestionSubItem(buf *bytes.Buffer, subItem models.SubItem) {
|
||||
if subItem.Title != "" {
|
||||
title := e.htmlCleaner.CleanHTML(subItem.Title)
|
||||
@ -222,7 +223,7 @@ func (e *MarkdownExporter) processQuestionSubItem(buf *bytes.Buffer, subItem mod
|
||||
}
|
||||
}
|
||||
|
||||
// processAnswers processes answer choices for quiz questions
|
||||
// processAnswers processes answer choices for quiz questions.
|
||||
func (e *MarkdownExporter) processAnswers(buf *bytes.Buffer, answers []models.Answer) {
|
||||
buf.WriteString("**Answers**:\n")
|
||||
for i, answer := range answers {
|
||||
@ -234,7 +235,7 @@ func (e *MarkdownExporter) processAnswers(buf *bytes.Buffer, answers []models.An
|
||||
}
|
||||
}
|
||||
|
||||
// processInteractiveItem handles interactive content
|
||||
// processInteractiveItem handles interactive content.
|
||||
func (e *MarkdownExporter) processInteractiveItem(buf *bytes.Buffer, item models.Item, headingPrefix string) {
|
||||
fmt.Fprintf(buf, "%s Interactive Content\n\n", headingPrefix)
|
||||
for _, subItem := range item.Items {
|
||||
@ -245,12 +246,12 @@ func (e *MarkdownExporter) processInteractiveItem(buf *bytes.Buffer, item models
|
||||
}
|
||||
}
|
||||
|
||||
// processDividerItem handles divider elements
|
||||
// processDividerItem handles divider elements.
|
||||
func (e *MarkdownExporter) processDividerItem(buf *bytes.Buffer) {
|
||||
buf.WriteString("---\n\n")
|
||||
}
|
||||
|
||||
// processUnknownItem handles unknown or unsupported item types
|
||||
// processUnknownItem handles unknown or unsupported item types.
|
||||
func (e *MarkdownExporter) processUnknownItem(buf *bytes.Buffer, item models.Item, headingPrefix string) {
|
||||
if len(item.Items) > 0 {
|
||||
caser := cases.Title(language.English)
|
||||
@ -261,7 +262,7 @@ func (e *MarkdownExporter) processUnknownItem(buf *bytes.Buffer, item models.Ite
|
||||
}
|
||||
}
|
||||
|
||||
// processGenericSubItem processes sub-items for unknown types
|
||||
// processGenericSubItem processes sub-items for unknown types.
|
||||
func (e *MarkdownExporter) processGenericSubItem(buf *bytes.Buffer, subItem models.SubItem) {
|
||||
if subItem.Title != "" {
|
||||
title := e.htmlCleaner.CleanHTML(subItem.Title)
|
||||
|
||||
@ -569,7 +569,7 @@ func TestNilPointerSafety(t *testing.T) {
|
||||
// TestJSONTagsPresence tests that JSON tags are properly defined.
|
||||
func TestJSONTagsPresence(t *testing.T) {
|
||||
// Test that important fields have JSON tags
|
||||
courseType := reflect.TypeOf(Course{})
|
||||
courseType := reflect.TypeFor[Course]()
|
||||
if courseType.Kind() == reflect.Struct {
|
||||
field, found := courseType.FieldByName("ShareID")
|
||||
if !found {
|
||||
@ -586,7 +586,7 @@ func TestJSONTagsPresence(t *testing.T) {
|
||||
}
|
||||
|
||||
// Test CourseInfo
|
||||
courseInfoType := reflect.TypeOf(CourseInfo{})
|
||||
courseInfoType := reflect.TypeFor[CourseInfo]()
|
||||
if courseInfoType.Kind() == reflect.Struct {
|
||||
field, found := courseInfoType.FieldByName("NavigationMode")
|
||||
if !found {
|
||||
@ -665,7 +665,7 @@ func BenchmarkCourse_JSONUnmarshal(b *testing.B) {
|
||||
}
|
||||
}
|
||||
|
||||
// compareMaps compares two interface{} values that should be maps
|
||||
// compareMaps compares two any values that should be maps.
|
||||
func compareMaps(original, unmarshaled any) bool {
|
||||
origMap, origOk := original.(map[string]any)
|
||||
unMap, unOk := unmarshaled.(map[string]any)
|
||||
@ -712,7 +712,7 @@ func compareMaps(original, unmarshaled any) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// compareLessons compares two Lesson structs accounting for JSON type conversion
|
||||
// compareLessons compares two Lesson structs accounting for JSON type conversion.
|
||||
func compareLessons(original, unmarshaled Lesson) bool {
|
||||
// Compare all fields except Position and Items
|
||||
if original.ID != unmarshaled.ID ||
|
||||
@ -735,7 +735,7 @@ func compareLessons(original, unmarshaled Lesson) bool {
|
||||
return compareItems(original.Items, unmarshaled.Items)
|
||||
}
|
||||
|
||||
// compareItems compares two Item slices accounting for JSON type conversion
|
||||
// compareItems compares two Item slices accounting for JSON type conversion.
|
||||
func compareItems(original, unmarshaled []Item) bool {
|
||||
if len(original) != len(unmarshaled) {
|
||||
return false
|
||||
@ -749,7 +749,7 @@ func compareItems(original, unmarshaled []Item) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// compareItem compares two Item structs accounting for JSON type conversion
|
||||
// compareItem compares two Item structs accounting for JSON type conversion.
|
||||
func compareItem(original, unmarshaled Item) bool {
|
||||
// Compare basic fields
|
||||
if original.ID != unmarshaled.ID ||
|
||||
|
||||
@ -61,7 +61,7 @@ func (p *ArticulateParser) FetchCourse(ctx context.Context, uri string) (*models
|
||||
|
||||
apiURL := p.buildAPIURL(shareID)
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, apiURL, nil)
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, apiURL, http.NoBody)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create request: %w", err)
|
||||
}
|
||||
|
||||
@ -130,7 +130,7 @@ func BenchmarkArticulateParser_LoadCourseFromFile(b *testing.B) {
|
||||
b.Fatalf("Failed to marshal: %v", err)
|
||||
}
|
||||
|
||||
if err := os.WriteFile(tempFile, data, 0644); err != nil {
|
||||
if err := os.WriteFile(tempFile, data, 0o644); err != nil {
|
||||
b.Fatalf("Failed to write file: %v", err)
|
||||
}
|
||||
|
||||
@ -177,7 +177,7 @@ func BenchmarkArticulateParser_LoadCourseFromFile_Large(b *testing.B) {
|
||||
b.Fatalf("Failed to marshal: %v", err)
|
||||
}
|
||||
|
||||
if err := os.WriteFile(tempFile, data, 0644); err != nil {
|
||||
if err := os.WriteFile(tempFile, data, 0o644); err != nil {
|
||||
b.Fatalf("Failed to write file: %v", err)
|
||||
}
|
||||
|
||||
|
||||
@ -144,7 +144,7 @@ func TestArticulateParser_FetchCourse_ContextDeadline(t *testing.T) {
|
||||
}
|
||||
|
||||
// TestArticulateParser_FetchCourse_ContextSuccess tests that FetchCourse
|
||||
// succeeds when context is not cancelled.
|
||||
// succeeds when context is not canceled.
|
||||
func TestArticulateParser_FetchCourse_ContextSuccess(t *testing.T) {
|
||||
testCourse := &models.Course{
|
||||
ShareID: "test-id",
|
||||
@ -173,7 +173,6 @@ func TestArticulateParser_FetchCourse_ContextSuccess(t *testing.T) {
|
||||
defer cancel()
|
||||
|
||||
course, err := parser.FetchCourse(ctx, "https://rise.articulate.com/share/test-id")
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("Expected no error, got: %v", err)
|
||||
}
|
||||
|
||||
@ -209,7 +209,7 @@ func TestArticulateParser_LoadCourseFromFile(t *testing.T) {
|
||||
t.Fatalf("Failed to marshal test course: %v", err)
|
||||
}
|
||||
|
||||
if err := os.WriteFile(tempFile, data, 0644); err != nil {
|
||||
if err := os.WriteFile(tempFile, data, 0o644); err != nil {
|
||||
t.Fatalf("Failed to write test file: %v", err)
|
||||
}
|
||||
|
||||
@ -268,7 +268,7 @@ func TestArticulateParser_LoadCourseFromFile_InvalidJSON(t *testing.T) {
|
||||
tempDir := t.TempDir()
|
||||
tempFile := filepath.Join(tempDir, "invalid.json")
|
||||
|
||||
if err := os.WriteFile(tempFile, []byte("invalid json content"), 0644); err != nil {
|
||||
if err := os.WriteFile(tempFile, []byte("invalid json content"), 0o644); err != nil {
|
||||
t.Fatalf("Failed to write test file: %v", err)
|
||||
}
|
||||
|
||||
|
||||
@ -14,7 +14,7 @@ var (
|
||||
// - Structured logging with slog
|
||||
// - Configuration via environment variables
|
||||
// - Context-aware HTTP requests
|
||||
// - Comprehensive benchmarks and examples
|
||||
// - Comprehensive benchmarks and examples.
|
||||
Version = "1.0.0"
|
||||
|
||||
// BuildTime is the time the binary was built.
|
||||
|
||||
Reference in New Issue
Block a user