Files
2026-01-22 15:49:12 +01:00

200 lines
5.7 KiB
JavaScript

'use strict';
const { JPDecoder } = require('../lib/jp-decoder');
const { PassThrough, Transform } = require('stream');
// Helper to collect stream output
const collectStream = stream =>
new Promise((resolve, reject) => {
const chunks = [];
stream.on('data', chunk => chunks.push(chunk));
stream.on('end', () => resolve(Buffer.concat(chunks)));
stream.on('error', reject);
});
// ============================================
// Constructor tests
// ============================================
module.exports['JPDecoder: constructor sets charset'] = test => {
let decoder = new JPDecoder('iso-2022-jp');
test.equal(decoder.charset, 'iso-2022-jp');
test.deepEqual(decoder.chunks, []);
test.equal(decoder.chunklen, 0);
test.done();
};
module.exports['JPDecoder: is a Transform stream'] = test => {
let decoder = new JPDecoder('iso-2022-jp');
test.ok(decoder instanceof Transform);
test.ok(typeof decoder.pipe === 'function');
test.ok(typeof decoder.write === 'function');
test.done();
};
// ============================================
// _transform tests
// ============================================
module.exports['JPDecoder: _transform accumulates buffer chunks'] = test => {
let decoder = new JPDecoder('iso-2022-jp');
let chunk1 = Buffer.from('hello');
let chunk2 = Buffer.from('world');
decoder._transform(chunk1, 'buffer', () => {
test.equal(decoder.chunks.length, 1);
test.equal(decoder.chunklen, 5);
decoder._transform(chunk2, 'buffer', () => {
test.equal(decoder.chunks.length, 2);
test.equal(decoder.chunklen, 10);
test.done();
});
});
};
module.exports['JPDecoder: _transform converts string to buffer'] = test => {
let decoder = new JPDecoder('iso-2022-jp');
let stringChunk = 'hello';
decoder._transform(stringChunk, 'utf8', () => {
test.equal(decoder.chunks.length, 1);
test.ok(Buffer.isBuffer(decoder.chunks[0]));
test.equal(decoder.chunks[0].toString(), 'hello');
test.done();
});
};
// ============================================
// _flush tests
// ============================================
module.exports['JPDecoder: _flush outputs accumulated data'] = async test => {
let decoder = new JPDecoder('utf-8');
let output = collectStream(decoder);
decoder.write(Buffer.from('hello '));
decoder.write(Buffer.from('world'));
decoder.end();
let result = await output;
test.equal(result.toString(), 'hello world');
test.done();
};
module.exports['JPDecoder: _flush converts ISO-2022-JP to Unicode'] = async test => {
let decoder = new JPDecoder('iso-2022-jp');
let output = collectStream(decoder);
// ISO-2022-JP encoded Japanese text for "nihongo" (Japanese)
// ESC $ B sequence switches to JIS X 0208, ESC ( B switches back to ASCII
let iso2022jp = Buffer.from([
0x1b,
0x24,
0x42, // ESC $ B - switch to JIS X 0208
0x46,
0x7c, // ni
0x4b,
0x5c, // hon
0x38,
0x6c, // go
0x1b,
0x28,
0x42 // ESC ( B - switch back to ASCII
]);
decoder.write(iso2022jp);
decoder.end();
let result = await output;
test.ok(result.length > 0);
test.done();
};
module.exports['JPDecoder: _flush handles conversion errors gracefully'] = async test => {
// Use an invalid/unknown charset to trigger error path
let decoder = new JPDecoder('invalid-charset-xyz');
let output = collectStream(decoder);
let input = Buffer.from('test data');
decoder.write(input);
decoder.end();
let result = await output;
// On error, should return original input
test.equal(result.toString(), 'test data');
test.done();
};
module.exports['JPDecoder: _flush handles empty input'] = async test => {
let decoder = new JPDecoder('iso-2022-jp');
let output = collectStream(decoder);
decoder.end();
let result = await output;
test.equal(result.length, 0);
test.done();
};
// ============================================
// Integration tests
// ============================================
module.exports['JPDecoder: works with pipe'] = async test => {
let source = new PassThrough();
let decoder = new JPDecoder('utf-8');
let output = collectStream(source.pipe(decoder));
source.write('hello ');
source.write('world');
source.end();
let result = await output;
test.equal(result.toString(), 'hello world');
test.done();
};
module.exports['JPDecoder: handles multiple small chunks'] = async test => {
let decoder = new JPDecoder('utf-8');
let output = collectStream(decoder);
// Write character by character
'hello'.split('').forEach(char => decoder.write(char));
decoder.end();
let result = await output;
test.equal(result.toString(), 'hello');
test.done();
};
module.exports['JPDecoder: handles Shift_JIS charset'] = async test => {
let decoder = new JPDecoder('shift_jis');
let output = collectStream(decoder);
// Shift_JIS encoded "test" in katakana (tesuto)
let shiftJis = Buffer.from([0x83, 0x65, 0x83, 0x58, 0x83, 0x67]);
decoder.write(shiftJis);
decoder.end();
let result = await output;
test.ok(result.length > 0);
test.done();
};
module.exports['JPDecoder: handles EUC-JP charset'] = async test => {
let decoder = new JPDecoder('euc-jp');
let output = collectStream(decoder);
// EUC-JP encoded Japanese character
let eucJp = Buffer.from([0xc6, 0xfc, 0xcb, 0xdc]); // nihon
decoder.write(eucJp);
decoder.end();
let result = await output;
test.ok(result.length > 0);
test.done();
};