The fulfilled comment looked for the first line containing the stream ID
as a substring, so a request for MTV.fr@SD linked the line of
BFMTV.fr@SD. Match the quoted tvg-id attribute instead.
playlist:edit saved the playlist without the raw option, so every title
was rebuilt from the API channel name and country instead of being
written back as read. For a stream whose channel is not in the database,
that becomes "undefined (undefined)". playlist:format, playlist:update
and playlist:test already save with { public: false, raw: true }.
playlist:validate decides which streams belong to the selected files by
comparing the raw command-line arguments with the paths returned by
Storage.list(). A path such as ./streams/us.m3u never matches
streams/us.m3u, so the file's own streams are put in the duplicate buffer
and every link is reported as already being in that same file.
Resolve the arguments with getStoragePath(), as playlist:format does.
The assertion compared stdout against a template literal that could never
match:
- The file was converted from LF to CRLF in 25fa704e14, so the literal
carries \r\n while the command's stdout uses \n.
- The literal starts with a newline, which only exists when consola prints
its [info] lines to stdout ahead of the table. Those are suppressed unless
DEBUG is set, so stdout begins directly at the table border.
Normalize line endings on both sides and trim the leading newline, so the
test asserts what it means to assert: that stdout contains the report table.
It now passes with and without DEBUG=true.