Repository: chicio/ID3TagEditor (swift)

Issue:
Extract ID3Tag description creation from ID3Tag class
Extract ID3Tag description creation from ID3Tag class

**Describe the solution you'd like**
At the moment the `debugDescription` property value creation is inside the `ID3Tag` class. Extract the creation of this string in an ad-hoc collaborator.

**Additional context**
See `ID3Tag` class.

Pull request description:
Extract ID3Tag description creation from ID3Tag class.

## Description
New adapter to generate the debugDescription of ID3Tag.

## Motivation and Context
Improve code quality

## How Has This Been Tested?
Unit test.

## Types of changes
- [X] Refactoring

## Checklist:
- [X] My code follows the code style of this project :beers:.
- [X] My change requires a change to the documentation :bulb: and I have updated the documentation accordingly.
- [X] I have read the [CONTRIBUTING](https://github.com/chicio/ID3TagEditor/blob/master/CONTRIBUTING.md) document :busts_in_silhouette:.
- [X] I have added tests to cover my changes :tada:.
- [X] All new and existing tests passed :white_check_mark:.

Patch:
diff --git a/ID3TagEditor.xcodeproj/project.pbxproj b/ID3TagEditor.xcodeproj/project.pbxproj
index 8c5a1225..2bd29137 100644
--- a/ID3TagEditor.xcodeproj/project.pbxproj
+++ b/ID3TagEditor.xcodeproj/project.pbxproj
@@ -301,6 +301,10 @@
 		455787F5204F104A00EE8756 /* ID3PictureTypeAdapterTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C50675D67C5E12BAE08DB28A /* ID3PictureTypeAdapterTest.swift */; };
 		455787F6204F129C00EE8756 /* MockPictureTypeAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = C50671FC32F01DE3E7FDAB6A /* MockPictureTypeAdapter.swift */; };
 		455787F7204F129C00EE8756 /* MockPictureTypeAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = C50671FC32F01DE3E7FDAB6A /* MockPictureTypeAdapter.swift */; };
+		455F6F2F254B5B29002FC259 /* ID3TagToStringAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 455F6F2E254B5B29002FC259 /* ID3TagToStringAdapter.swift */; };
+		455F6F30254B5B29002FC259 /* ID3TagToStringAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 455F6F2E254B5B29002FC259 /* ID3TagToStringAdapter.swift */; };
+		455F6F31254B5B29002FC259 /* ID3TagToStringAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 455F6F2E254B5B29002FC259 /* ID3TagToStringAdapter.swift */; };
+		455F6F32254B5B29002FC259 /* ID3TagToStringAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 455F6F2E254B5B29002FC259 /* ID3TagToStringAdapter.swift */; };
 		4562C1E221172ED800AFE22E /* ID3RecordingDayMonthFrameCreator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4562C1E121172ED800AFE22E /* ID3RecordingDayMonthFrameCreator.swift */; };
 		4562C1E321172ED800AFE22E /* ID3RecordingDayMonthFrameCreator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4562C1E121172ED800AFE22E /* ID3RecordingDayMonthFrameCreator.swift */; };
 		4562C1E421172ED800AFE22E /* ID3RecordingDayMonthFrameCreator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4562C1E121172ED800AFE22E /* ID3RecordingDayMonthFrameCreator.swift */; };
@@ -1125,6 +1129,7 @@
 		455CF9892340C4D7004C880A /* CONTRIBUTING.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = CONTRIBUTING.md; sourceTree = "<group>"; };
 		455CF98A2340C4D7004C880A /* CODE_OF_CONDUCT.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = CODE_OF_CONDUCT.md; sourceTree = "<group>"; };
 		455CF98B2340C4E1004C880A /* PULL_REQUEST_TEMPLATE.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = PULL_REQUEST_TEMPLATE.md; sourceTree = "<group>"; };
+		455F6F2E254B5B29002FC259 /* ID3TagToStringAdapter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ID3TagToStringAdapter.swift; sourceTree = "<group>"; };
 		4562C1E121172ED800AFE22E /* ID3RecordingDayMonthFrameCreator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ID3RecordingDayMonthFrameCreator.swift; sourceTree = "<group>"; };
 		4562C1E6211731B100AFE22E /* ID3RecordingHourMinuteFrameCreator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ID3RecordingHourMinuteFrameCreator.swift; sourceTree = "<group>"; };
 		4562C1EB211737C100AFE22E /* ID3RecordingDayMonthFrameCreatorTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ID3RecordingDayMonthFrameCreatorTest.swift; sourceTree = "<group>"; };
@@ -1628,6 +1633,7 @@
 				45D551C925446431003347B7 /* ID32v2TagBuilder.swift */,
 				45D551D52544649A003347B7 /* ID32v3TagBuilder.swift */,
 				45D551F625446A1B003347B7 /* ID32v4TagBuilder.swift */,
+				455F6F2E254B5B29002FC259 /* ID3TagToStringAdapter.swift */,
 			);
 			path = Tag;
 			sourceTree = "<group>";
@@ -2696,6 +2702,7 @@
 				4528326E2044C7BE00458375 /* ID3FrameConfiguration.swift in Sources */,
 				519C342D2405041E008F3BDE /* ID3iTunesPodcastCategoryFrameCreator.swift in Sources */,
 				452832822044C7BE00458375 /* PaddingRemover.swift in Sources */,
+				455F6F2F254B5B29002FC259 /* ID3TagToStringAdapter.swift in Sources */,
 				452832702044C7BE00458375 /* UInt32ToByteArrayAdapterUsingUnsafePointer.swift in Sources */,
 				45775EE72107C37A00B1B3FE /* ID3StringEncodingConverter.swift in Sources */,
 				519C33F12405041E008F3BDE /* ID3FileOwnerFrameCreator.swift in Sources */,
@@ -2960,6 +2967,7 @@
 				4528AEFF210B508400CB7A2E /* ID3RecordingTimeFrameContentParsingOperation.swift in Sources */,
 				519C342E2405041E008F3BDE /* ID3iTunesPodcastCategoryFrameCreator.swift in Sources */,
 				4528326F2044C7BE00458375 /* ID3FrameConfiguration.swift in Sources */,
+				455F6F30254B5B29002FC259 /* ID3TagToStringAdapter.swift in Sources */,
 				452832832044C7BE00458375 /* PaddingRemover.swift in Sources */,
 				4528AF24210B84D200CB7A2E /* ID3TrackPositionFrameContentParsingOperationFactory.swift in Sources */,
 				519C33F22405041E008F3BDE /* ID3FileOwnerFrameCreator.swift in Sources */,
@@ -3224,6 +3232,7 @@
 				519C34072405041E008F3BDE /* ID3CopyrightFrameCreator.swift in Sources */,
 				4528AF00210B508400CB7A2E /* ID3RecordingTimeFrameContentParsingOperation.swift in Sources */,
 				519C342F2405041E008F3BDE /* ID3iTunesPodcastCategoryFrameCreator.swift in Sources */,
+				455F6F31254B5B29002FC259 /* ID3TagToStringAdapter.swift in Sources */,
 				45541B8520598FA60025A8BF /* ID3ArtistFrameCreator.swift in Sources */,
 				4528AF25210B84D200CB7A2E /* ID3TrackPositionFrameContentParsingOperationFactory.swift in Sources */,
 				519C33F32405041E008F3BDE /* ID3FileOwnerFrameCreator.swift in Sources */,
@@ -3488,6 +3497,7 @@
 				519C34082405041E008F3BDE /* ID3CopyrightFrameCreator.swift in Sources */,
 				4528AF01210B508400CB7A2E /* ID3RecordingTimeFrameContentParsingOperation.swift in Sources */,
 				519C34302405041E008F3BDE /* ID3iTunesPodcastCategoryFrameCreator.swift in Sources */,
+				455F6F32254B5B29002FC259 /* ID3TagToStringAdapter.swift in Sources */,
 				45F833F0205905EF0046C804 /* ID3ArtistFrameCreator.swift in Sources */,
 				4528AF26210B84D200CB7A2E /* ID3TrackPositionFrameContentParsingOperationFactory.swift in Sources */,
 				519C33F42405041E008F3BDE /* ID3FileOwnerFrameCreator.swift in Sources */,
diff --git a/Source/Tag/ID3Tag.swift b/Source/Tag/ID3Tag.swift
index c1efb82c..f5b41798 100644
--- a/Source/Tag/ID3Tag.swift
+++ b/Source/Tag/ID3Tag.swift
@@ -5,8 +5,6 @@
 //  2018 Fabrizio Duroni.
 //
 
-// swiftlint:disable line_length
-
 import Foundation
 
 /**
@@ -21,57 +19,7 @@ public class ID3Tag: CustomDebugStringConvertible {
     }()
     /// ID3Tag description, useful for debug.
     public var debugDescription: String {
-        return """
-        ID3Tag:
-        - size: \(self.properties.size)
-        - version: \(self.properties.version)
-        - artist: \((self.frames[.artist] as? ID3FrameWithStringContent)?.content ?? "-")
-        - composer: \((self.frames[.composer] as? ID3FrameWithStringContent)?.content ?? "-")
-        - conductor: \((self.frames[.conductor] as? ID3FrameWithStringContent)?.content ?? "-")
-        - contentGrouping: \((self.frames[.contentGrouping] as? ID3FrameWithStringContent)?.content ?? "-")
-        - copyright: \((self.frames[.copyright] as? ID3FrameWithStringContent)?.content ?? "-")
-        - encodedBy: \((self.frames[.encodedBy] as? ID3FrameWithStringContent)?.content ?? "-")
-        - encoderSettings: \((self.frames[.encoderSettings] as? ID3FrameWithStringContent)?.content ?? "-")
-        - fileOwner: \((self.frames[.fileOwner] as? ID3FrameWithStringContent)?.content ?? "-")
-        - iTunesGrouping: \((self.frames[.iTunesGrouping] as? ID3FrameWithStringContent)?.content ?? "-")
-        - lyricist: \((self.frames[.lyricist] as? ID3FrameWithStringContent)?.content ?? "-")
-        - mixArtist: \((self.frames[.mixArtist] as? ID3FrameWithStringContent)?.content ?? "-")
-        - iTunesMovementIndex: \((self.frames[.iTunesMovementIndex] as? ID3FrameWithIntegerContent)?.debugDescription ?? "-")
-        - iTunesMovementCount: \((self.frames[.iTunesMovementCount] as? ID3FrameWithIntegerContent)?.debugDescription ?? "-")
-        - iTunesMovementName: \((self.frames[.iTunesMovementName] as? ID3FrameWithStringContent)?.content ?? "-")
-        - podcastCategory: \((self.frames[.iTunesPodcastCategory] as? ID3FrameWithStringContent)?.content ?? "-")
-        - podcastDescription: \((self.frames[.iTunesPodcastDescription] as? ID3FrameWithStringContent)?.content ?? "-")
-        - podcastID: \((self.frames[.iTunesPodcastID] as? ID3FrameWithStringContent)?.content ?? "-")
-        - podcastKeywords: \((self.frames[.iTunesPodcastKeywords] as? ID3FrameWithStringContent)?.content ?? "-")
-        - publisher: \((self.frames[.publisher] as? ID3FrameWithStringContent)?.content ?? "-")
-        - subtitle: \((self.frames[.subtitle] as? ID3FrameWithStringContent)?.content ?? "-")
-        - albumArtist: \((self.frames[.albumArtist] as? ID3FrameWithStringContent)?.content ?? "-")
-        - title: \((self.frames[.title] as? ID3FrameWithStringContent)?.content ?? "-")
-        - trackPosition: \((self.frames[.trackPosition] as? ID3FramePartOfTotal)?.debugDescription ?? "-")
-        - discPosition: \((self.frames[.discPosition] as? ID3FramePartOfTotal)?.debugDescription ?? "-")
-        - album: \((self.frames[.album] as? ID3FrameWithStringContent)?.content ?? "-")
-        - recordingDateTime: \(
-            (self.frames[.recordingDateTime] as? ID3FrameRecordingDateTime)?.recordingDateTime.debugDescription ?? "-"
-        )
-        - recordingYear: \((self.frames[.recordingYear] as? ID3FrameRecordingYear)?.debugDescription ?? "-")
-        - recordingDayMonth: \((self.frames[.recordingDayMonth] as? ID3FrameRecordingDayMonth)?.debugDescription ?? "-")
-        - recordingHourMinute: \((self.frames[.recordingHourMinute] as? ID3FrameRecordingHourMinute)?.debugDescription ?? "-")
-        - genre: \((self.frames[.genre] as? ID3FrameGenre)?.debugDescription ?? "-")
-        - attachedPicture:\(ID3PictureType.allCases.reduce("", { (accumulator: String, current: ID3PictureType) in
-            if let frameDescription = (self.frames[.attachedPicture(current)] as? ID3FrameAttachedPicture)?.debugDescription {
-                return accumulator + "\n" + frameDescription + "\n"
-            }
-
-            return accumulator
-        }))
-        - unsynchronisedLyrics:\(ID3FrameContentLanguage.allCases.reduce("", { (accumulator: String, current: ID3FrameContentLanguage) in
-            if let frameDescription = (self.frames[.unsynchronizedLyrics(current)] as? ID3FrameWithLocalizedContent)?.debugDescription {
-                return accumulator + "\n" + frameDescription + "\n"
-            }
-
-            return accumulator
-        }))
-        """
+        return ID3TagToStringAdapter().adapt(id3Tag: self)
     }
 
     init(version: ID3Version, frames: [FrameName: ID3Frame]) {
diff --git a/Source/Tag/ID3TagToStringAdapter.swift b/Source/Tag/ID3TagToStringAdapter.swift
new file mode 100644
index 00000000..e3924332
--- /dev/null
+++ b/Source/Tag/ID3TagToStringAdapter.swift
@@ -0,0 +1,77 @@
+//
+//  ID3TagToStringAdapter.swift
+//  ID3TagEditor
+//
+//  Created by Fabrizio Duroni on 29.10.20.
+//  2020 Fabrizio Duroni.
+//
+
+// swiftlint:disable line_length
+// swiftlint:disable function_body_length
+
+import Foundation
+
+class ID3TagToStringAdapter {
+    func adapt(id3Tag: ID3Tag) -> String {
+        return """
+        ID3Tag:
+        - size: \(id3Tag.properties.size)
+        - version: \(id3Tag.properties.version)
+        - artist: \(adaptFrameWithStringContentFrom(id3Tag: id3Tag, frameName: .artist))
+        - composer: \(adaptFrameWithStringContentFrom(id3Tag: id3Tag, frameName: .composer))
+        - conductor: \(adaptFrameWithStringContentFrom(id3Tag: id3Tag, frameName: .conductor))
+        - contentGrouping: \(adaptFrameWithStringContentFrom(id3Tag: id3Tag, frameName: .contentGrouping))
+        - copyright: \(adaptFrameWithStringContentFrom(id3Tag: id3Tag, frameName: .copyright))
+        - encodedBy: \(adaptFrameWithStringContentFrom(id3Tag: id3Tag, frameName: .encodedBy))
+        - encoderSettings: \(adaptFrameWithStringContentFrom(id3Tag: id3Tag, frameName: .encoderSettings))
+        - fileOwner: \(adaptFrameWithStringContentFrom(id3Tag: id3Tag, frameName: .fileOwner))
+        - lyricist: \(adaptFrameWithStringContentFrom(id3Tag: id3Tag, frameName: .lyricist))
+        - mixArtist: \(adaptFrameWithStringContentFrom(id3Tag: id3Tag, frameName: .mixArtist))
+        - publisher: \(adaptFrameWithStringContentFrom(id3Tag: id3Tag, frameName: .publisher))
+        - subtitle: \(adaptFrameWithStringContentFrom(id3Tag: id3Tag, frameName: .subtitle))
+        - albumArtist: \(adaptFrameWithStringContentFrom(id3Tag: id3Tag, frameName: .albumArtist))
+        - title: \(adaptFrameWithStringContentFrom(id3Tag: id3Tag, frameName: .title))
+        - trackPosition: \((id3Tag.frames[.trackPosition] as? ID3FramePartOfTotal)?.debugDescription ?? "-")
+        - discPosition: \((id3Tag.frames[.discPosition] as? ID3FramePartOfTotal)?.debugDescription ?? "-")
+        - album: \(adaptFrameWithStringContentFrom(id3Tag: id3Tag, frameName: .album))
+        - recordingDateTime: \(
+            (id3Tag.frames[.recordingDateTime] as? ID3FrameRecordingDateTime)?.recordingDateTime.debugDescription ?? "-"
+        )
+        - recordingYear: \((id3Tag.frames[.recordingYear] as? ID3FrameRecordingYear)?.debugDescription ?? "-")
+        - recordingDayMonth: \((id3Tag.frames[.recordingDayMonth] as? ID3FrameRecordingDayMonth)?.debugDescription ?? "-")
+        - recordingHourMinute: \((id3Tag.frames[.recordingHourMinute] as? ID3FrameRecordingHourMinute)?.debugDescription ?? "-")
+        - genre: \((id3Tag.frames[.genre] as? ID3FrameGenre)?.debugDescription ?? "-")
+        - attachedPicture:\(ID3PictureType.allCases.reduce("", { (accumulator: String, current: ID3PictureType) in
+            if let frameDescription = (id3Tag.frames[.attachedPicture(current)] as? ID3FrameAttachedPicture)?.debugDescription {
+                return accumulator + "\n" + frameDescription + "\n"
+            }
+
+            return accumulator
+        }))
+        - unsynchronisedLyrics:\(adaptFrameWithLocalizedContent(id3Tag: id3Tag, frameName: FrameName.unsynchronizedLyrics))
+        - comments:\(adaptFrameWithLocalizedContent(id3Tag: id3Tag, frameName: FrameName.comment))
+        - iTunesGrouping: \(adaptFrameWithStringContentFrom(id3Tag: id3Tag, frameName: .iTunesGrouping))
+        - iTunesMovementIndex: \((id3Tag.frames[.iTunesMovementIndex] as? ID3FrameWithIntegerContent)?.debugDescription ?? "-")
+        - iTunesMovementCount: \((id3Tag.frames[.iTunesMovementCount] as? ID3FrameWithIntegerContent)?.debugDescription ?? "-")
+        - iTunesMovementName: \(adaptFrameWithStringContentFrom(id3Tag: id3Tag, frameName: .iTunesMovementName))
+        - iTunesPodcastCategory: \(adaptFrameWithStringContentFrom(id3Tag: id3Tag, frameName: .iTunesPodcastCategory))
+        - iTunesPodcastDescription: \(adaptFrameWithStringContentFrom(id3Tag: id3Tag, frameName: .iTunesPodcastDescription))
+        - iTunesPodcastID: \(adaptFrameWithStringContentFrom(id3Tag: id3Tag, frameName: .iTunesPodcastID))
+        - iTunesPodcastKeywords: \(adaptFrameWithStringContentFrom(id3Tag: id3Tag, frameName: .iTunesPodcastKeywords))
+        """
+    }
+
+    private func adaptFrameWithStringContentFrom(id3Tag: ID3Tag, frameName: FrameName) -> String {
+        return (id3Tag.frames[frameName] as? ID3FrameWithStringContent)?.content ?? "-"
+    }
+
+    private func adaptFrameWithLocalizedContent(id3Tag: ID3Tag, frameName: (ID3FrameContentLanguage) -> FrameName) -> String {
+        return ID3FrameContentLanguage.allCases.reduce("", { (accumulator: String, current: ID3FrameContentLanguage) in
+            if let frameDescription = (id3Tag.frames[frameName(current)] as? ID3FrameWithLocalizedContent)?.debugDescription {
+                return accumulator + "\n" + frameDescription + "\n"
+            }
+
+            return accumulator
+        })
+    }
+}


Test patch:
diff --git a/Tests/Tag/ID3TagTest.swift b/Tests/Tag/ID3TagTest.swift
index f2c9a4cc..04f28c2c 100644
--- a/Tests/Tag/ID3TagTest.swift
+++ b/Tests/Tag/ID3TagTest.swift
@@ -8,6 +8,7 @@
 
 // swiftlint:disable line_length
 // swiftlint:disable function_body_length
+// swiftlint:disable type_body_length
 
 import XCTest
 @testable import ID3TagEditor
@@ -49,6 +50,8 @@ class ID3TagTest: XCTestCase {
                 .attachedPicture(.backCover): ID3FrameAttachedPicture(picture: artBack, type: .backCover, format: .jpeg),
                 .unsynchronizedLyrics(.ita): ID3FrameWithLocalizedContent(language: ID3FrameContentLanguage.ita, contentDescription: "CD", content: "v3 ita unsync lyrics"),
                 .unsynchronizedLyrics(.eng): ID3FrameWithLocalizedContent(language: ID3FrameContentLanguage.eng, contentDescription: "CD", content: "v3 eng unsync lyrics"),
+                .comment(.ita): ID3FrameWithLocalizedContent(language: ID3FrameContentLanguage.ita, contentDescription: "CD", content: "v3 ita comment"),
+                .comment(.eng): ID3FrameWithLocalizedContent(language: ID3FrameContentLanguage.eng, contentDescription: "CD", content: "v3 eng comment"),
                 .iTunesGrouping: ID3FrameWithStringContent(content: "ItunesGrouping V3"),
                 .iTunesMovementName: ID3FrameWithStringContent(content: "MovementName V3"),
                 .iTunesMovementIndex: ID3FrameWithIntegerContent(value: 6),
@@ -74,16 +77,8 @@ class ID3TagTest: XCTestCase {
             - encodedBy: EncodedBy V3
             - encoderSettings: EncoderSettings V3
             - fileOwner: FileOwner V3
-            - iTunesGrouping: ItunesGrouping V3
             - lyricist: Lyricist V3
             - mixArtist: MixArtist V3
-            - iTunesMovementIndex: 6
-            - iTunesMovementCount: 13
-            - iTunesMovementName: MovementName V3
-            - podcastCategory: PodcastCategory V3
-            - podcastDescription: PodcastDescription V3
-            - podcastID: PodcastID V3
-            - podcastKeywords: PodcastKeywords V3
             - publisher: Publisher V3
             - subtitle: Subtitle V3
             - albumArtist: album artist V3
@@ -110,6 +105,23 @@ class ID3TagTest: XCTestCase {
             contentDescription: CD
             content: v3 ita unsync lyrics
 
+            - comments:
+            language: eng
+            contentDescription: CD
+            content: v3 eng comment
+
+            language: ita
+            contentDescription: CD
+            content: v3 ita comment
+
+            - iTunesGrouping: ItunesGrouping V3
+            - iTunesMovementIndex: 6
+            - iTunesMovementCount: 13
+            - iTunesMovementName: MovementName V3
+            - iTunesPodcastCategory: PodcastCategory V3
+            - iTunesPodcastDescription: PodcastDescription V3
+            - iTunesPodcastID: PodcastID V3
+            - iTunesPodcastKeywords: PodcastKeywords V3
             """)
     }
 
@@ -144,6 +156,8 @@ class ID3TagTest: XCTestCase {
                 .attachedPicture(.backCover): ID3FrameAttachedPicture(picture: artBack, type: .backCover, format: .jpeg),
                 .unsynchronizedLyrics(.ita): ID3FrameWithLocalizedContent(language: ID3FrameContentLanguage.ita, contentDescription: "CD", content: "V4 ita unsync lyrics"),
                 .unsynchronizedLyrics(.eng): ID3FrameWithLocalizedContent(language: ID3FrameContentLanguage.eng, contentDescription: "CD", content: "V4 eng unsync lyrics"),
+                .comment(.ita): ID3FrameWithLocalizedContent(language: ID3FrameContentLanguage.ita, contentDescription: "CD", content: "V4 ita comment"),
+                .comment(.eng): ID3FrameWithLocalizedContent(language: ID3FrameContentLanguage.eng, contentDescription: "CD", content: "V4 eng comment"),
                 .iTunesGrouping: ID3FrameWithStringContent(content: "ItunesGrouping V4"),
                 .iTunesMovementName: ID3FrameWithStringContent(content: "MovementName V4"),
                 .iTunesMovementIndex: ID3FrameWithIntegerContent(value: 6),
@@ -169,16 +183,8 @@ class ID3TagTest: XCTestCase {
             - encodedBy: EncodedBy V4
             - encoderSettings: EncoderSettings V4
             - fileOwner: FileOwner V4
-            - iTunesGrouping: ItunesGrouping V4
             - lyricist: Lyricist V4
             - mixArtist: MixArtist V4
-            - iTunesMovementIndex: 6
-            - iTunesMovementCount: 13
-            - iTunesMovementName: MovementName V4
-            - podcastCategory: PodcastCategory V4
-            - podcastDescription: PodcastDescription V4
-            - podcastID: PodcastID V4
-            - podcastKeywords: PodcastKeywords V4
             - publisher: Publisher V4
             - subtitle: Subtitle V4
             - albumArtist: album artist V4
@@ -205,6 +211,23 @@ class ID3TagTest: XCTestCase {
             contentDescription: CD
             content: V4 ita unsync lyrics
 
+            - comments:
+            language: eng
+            contentDescription: CD
+            content: V4 eng comment
+
+            language: ita
+            contentDescription: CD
+            content: V4 ita comment
+
+            - iTunesGrouping: ItunesGrouping V4
+            - iTunesMovementIndex: 6
+            - iTunesMovementCount: 13
+            - iTunesMovementName: MovementName V4
+            - iTunesPodcastCategory: PodcastCategory V4
+            - iTunesPodcastDescription: PodcastDescription V4
+            - iTunesPodcastID: PodcastID V4
+            - iTunesPodcastKeywords: PodcastKeywords V4
             """
         )
     }