200 lines
5.7 KiB
JavaScript
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();
|
|
};
|