idna-uts46-hx
Version:
Convert Domain Names correctly from IDN to Punycode and vice-versa and offer TR46 processing.
587 lines (553 loc) • 15.9 kB
JavaScript
'use strict';
import assert from 'assert';
import * as uts46 from '../src/index.js';
suite('toASCII', function () {
test('Convert method tests', function () {
const d = String.fromCodePoint(0xd0000);
assert.strict.deepEqual(uts46.convert(d), { IDN: d, PC: d });
assert.strict.deepEqual(uts46.convert('öbb.at'), {
IDN: 'öbb.at',
PC: 'xn--bb-eka.at',
});
assert.strict.deepEqual(uts46.convert(['öbb.at', 'faß.de']), {
IDN: ['öbb.at', 'faß.de'],
PC: ['xn--bb-eka.at', 'xn--fa-hia.de'],
});
});
test('Basic tests', function () {
assert.strict.equal(uts46.toAscii('öbb.at'), 'xn--bb-eka.at');
assert.strict.equal(uts46.toAscii('xn--bb-eka.at'), 'xn--bb-eka.at');
assert.strict.equal(uts46.toAscii('XN--BB-EKA.AT'), 'xn--bb-eka.at');
assert.strict.equal(
uts46.toAscii('faß.de', {
transitionalProcessing: true,
}),
'fass.de',
);
assert.strict.equal(
uts46.toAscii('faß.de', {
transitionalProcessing: false,
}),
'xn--fa-hia.de',
);
assert.strict.equal(
uts46.toAscii('xn--fa-hia.de', {
transitionalProcessing: true,
}),
'xn--fa-hia.de',
);
// Default to not processing STD3 rules (that's what URL.domainToASCII
// is specifying).
assert.strict.equal(uts46.toAscii('not=std3'), 'not=std3');
assert.throws(function () {
uts46.toAscii('not=std3', {
useSTD3ASCIIRules: true,
});
});
assert.throws(function () {
uts46.toAscii(String.fromCodePoint(0xd0000));
});
// Check verify DNS length
assert.strict.equal(
uts46.toAscii('', {
verifyDNSLength: false,
}),
'',
);
assert.throws(function () {
uts46.toAscii('', {
verifyDNSLength: true,
});
});
});
test('Verify DNS length parameter', function () {
assert.throws(function () {
uts46.toAscii('this..is.almost.right', {
transitionalProcessing: false,
verifyDNSLength: true,
});
});
assert.throws(function () {
// 254 characters
uts46.toAscii('a.'.repeat(126) + 'aa', {
verifyDNSLength: true,
});
});
assert.doesNotThrow(function () {
// 253 characters
uts46.toAscii('a.'.repeat(126) + 'a', {
verifyDNSLength: true,
});
});
assert.throws(function () {
uts46.toAscii('a'.repeat(64), {
verifyDNSLength: true,
});
});
assert.doesNotThrow(function () {
uts46.toAscii('a'.repeat(63), {
verifyDNSLength: true,
});
});
// Default is to not verify it.
assert.strict.equal(uts46.toAscii(''), '');
});
test('Defaults to transitional', function () {
assert.strict.equal(
uts46.toAscii('faß.de', { transitionalProcessing: true }),
'fass.de',
);
});
test('Non-BMP characters', function () {
assert.strict.equal(uts46.toAscii('\ud83d\udca9'), 'xn--ls8h');
// This non-BMP character gets mapped to another non-BMP character.
assert.strict.equal(uts46.toAscii('\ud87e\udcca'), 'xn--w60j');
// ... and let's throw in a variant selector before it (which gets ignored)!
assert.strict.equal(uts46.toAscii('\udb40\udd00\ud87e\udcca'), 'xn--w60j');
});
});
suite('toUnicode', function () {
test('Basic tests', function () {
assert.strict.equal(uts46.toUnicode('öbb.at'), 'öbb.at');
assert.strict.equal(uts46.toUnicode('Öbb.at'), 'öbb.at');
assert.strict.equal(uts46.toUnicode('O\u0308bb.at'), 'öbb.at');
assert.strict.equal(uts46.toUnicode('xn--bb-eka.at'), 'öbb.at');
assert.strict.equal(uts46.toUnicode('faß.de'), 'faß.de');
assert.strict.equal(uts46.toUnicode('fass.de'), 'fass.de');
assert.strict.equal(uts46.toUnicode('xn--fa-hia.de'), 'faß.de');
// Default to not processing STD3 rules (that's what URL.domainToASCII
// is specifying).
assert.strict.equal(uts46.toUnicode('not=std3'), 'not=std3');
assert.throws(function () {
uts46.toUnicode('not=std3', {
useSTD3ASCIIRules: true,
});
});
assert.throws(function () {
uts46.toUnicode(String.fromCodePoint(0xd0000));
});
});
test('Non-BMP characters', function () {
assert.strict.equal(uts46.toUnicode('\ud83d\udca9'), '\ud83d\udca9');
// This non-BMP character gets mapped to another non-BMP character.
assert.strict.equal(uts46.toUnicode('\ud87e\udcca'), '\ud84c\udc0a');
// ... and let's throw in a variant selector before it (which gets ignored)!
assert.strict.equal(
uts46.toUnicode('\udb40\udd00\ud87e\udcca'),
'\ud84c\udc0a',
);
});
});
suite('unicode.org', function () {
test('Unicode Utilities: Internationalized Domain Names (IDN)', function () {
// http://unicode.org/cldr/utility/idna.jsp
// NOTE: some of the results below need further research as they are marked
// as error cases on the web page but working here (or otherwise)
// fass.de
assert.strict.equal(uts46.toUnicode('fass.de'), 'fass.de');
assert.strict.equal(
uts46.toAscii('fass.de', {
transitionalProcessing: true,
}),
'fass.de',
);
assert.strict.equal(
uts46.toAscii('fass.de', {
transitionalProcessing: false,
}),
'fass.de',
);
// faß.de
assert.strict.equal(uts46.toUnicode('faß.de'), 'faß.de');
assert.strict.equal(
uts46.toAscii('faß.de', {
transitionalProcessing: true,
}),
'fass.de',
);
assert.strict.equal(
uts46.toAscii('faß.de', {
transitionalProcessing: false,
}),
'xn--fa-hia.de',
);
// fäß.de
assert.strict.equal(uts46.toUnicode('fäß.de'), 'fäß.de');
assert.strict.equal(
uts46.toAscii('fäß.de', {
transitionalProcessing: true,
}),
'xn--fss-qla.de',
);
assert.strict.equal(
uts46.toAscii('fäß.de', {
transitionalProcessing: false,
}),
'xn--f-qfao.de',
);
// xn--fa-hia.de
assert.strict.equal(uts46.toUnicode('xn--fa-hia.de'), 'faß.de');
assert.strict.equal(
uts46.toAscii('xn--fa-hia.de', {
transitionalProcessing: true,
}),
'xn--fa-hia.de',
);
assert.strict.equal(
uts46.toAscii('xn--fa-hia.de', {
transitionalProcessing: false,
}),
'xn--fa-hia.de',
);
// ₹.com
assert.strict.equal(uts46.toUnicode('₹.com'), '₹.com'); // no error thrown
assert.strict.equal(
uts46.toAscii('₹.com', {
transitionalProcessing: true,
}),
'xn--yzg.com',
);
assert.strict.equal(
uts46.toAscii('₹.com', {
transitionalProcessing: false,
}),
'xn--yzg.com',
); // no error thrown
// 𑀓.com
assert.strict.equal(uts46.toUnicode('𑀓.com'), '𑀓.com'); // no error thrown
assert.strict.equal(
uts46.toAscii('𑀓.com', {
transitionalProcessing: true,
}),
'xn--n00d.com',
);
assert.strict.equal(
uts46.toAscii('𑀓.com', {
transitionalProcessing: false,
}),
'xn--n00d.com',
);
// \u0080.com
assert.throws(function () {
uts46.toUnicode('\u0080.com');
});
assert.throws(function () {
uts46.toAscii('\u0080.com', {
transitionalProcessing: true,
});
});
assert.throws(function () {
uts46.toAscii('\u0080.com', {
transitionalProcessing: false,
});
});
// xn--a.com [might be wrong one compare results in web]
assert.throws(function () {
uts46.toUnicode('xn--a.com');
});
assert.throws(function () {
uts46.toAscii('xn--a.com', {
transitionalProcessing: true,
});
});
assert.throws(function () {
uts46.toAscii('xn--a.com', {
transitionalProcessing: false,
});
});
/* jshint -W100 */
// ab
assert.strict.equal(
uts46.toUnicode('ab', {
transitionalProcessing: false,
}),
'a\u200Cb',
); // no error thrown
assert.strict.equal(
uts46.toAscii('ab', {
transitionalProcessing: true,
}),
'ab',
);
assert.strict.equal(
uts46.toAscii('ab', {
transitionalProcessing: false,
}),
'xn--ab-j1t',
);
/* jshint +W100 */
// xn--ab-j1t
assert.strict.equal(uts46.toUnicode('xn--ab-j1t'), 'a\u200Cb'); // no error thrown
assert.strict.equal(
uts46.toAscii('xn--ab-j1t', {
// no error thrown
transitionalProcessing: true,
}),
'xn--ab-j1t',
);
assert.strict.equal(
uts46.toAscii('xn--ab-j1t', {
transitionalProcessing: false,
}),
'xn--ab-j1t',
);
// öbb.at
assert.strict.equal(uts46.toUnicode('öbb.at'), 'öbb.at');
assert.strict.equal(
uts46.toAscii('öbb.at', {
transitionalProcessing: true,
}),
'xn--bb-eka.at',
);
assert.strict.equal(
uts46.toAscii('öbb.at', {
transitionalProcessing: false,
}),
'xn--bb-eka.at',
);
// ÖBB.at
assert.strict.equal(uts46.toUnicode('ÖBB.at'), 'öbb.at');
assert.strict.equal(
uts46.toAscii('ÖBB.at', {
transitionalProcessing: true,
}),
'xn--bb-eka.at',
);
assert.strict.equal(
uts46.toAscii('ÖBB.at', {
transitionalProcessing: false,
}),
'xn--bb-eka.at',
);
// ȡog.de
assert.strict.equal(uts46.toUnicode('ȡog.de'), 'ȡog.de');
assert.strict.equal(
uts46.toAscii('ȡog.de', {
transitionalProcessing: true,
}),
'xn--og-09a.de',
);
assert.strict.equal(
uts46.toAscii('ȡog.de', {
transitionalProcessing: false,
}),
'xn--og-09a.de',
);
// ☕.de
assert.strict.equal(uts46.toUnicode('☕.de'), '☕.de');
assert.strict.equal(
uts46.toAscii('☕.de', {
transitionalProcessing: true,
}),
'xn--53h.de',
);
assert.strict.equal(
uts46.toAscii('☕.de', {
transitionalProcessing: false,
}),
'xn--53h.de',
);
// I♥NY.de
assert.strict.equal(uts46.toUnicode('I♥NY.de'), 'i♥ny.de');
assert.strict.equal(
uts46.toAscii('I♥NY.de', {
transitionalProcessing: true,
}),
'xn--iny-zx5a.de',
);
assert.strict.equal(
uts46.toAscii('I♥NY.de', {
transitionalProcessing: false,
}),
'xn--iny-zx5a.de',
);
// ABC・日本.co.jp
assert.strict.equal(
uts46.toUnicode('ABC・日本.co.jp'),
'abc・日本.co.jp',
);
assert.strict.equal(
uts46.toAscii('ABC・日本.co.jp', {
transitionalProcessing: true,
}),
'xn--abc-rs4b422ycvb.co.jp',
);
assert.strict.equal(
uts46.toAscii('ABC・日本.co.jp', {
transitionalProcessing: false,
}),
'xn--abc-rs4b422ycvb.co.jp',
);
// 日本。co。jp
assert.strict.equal(uts46.toUnicode('日本。co。jp'), '日本.co.jp');
assert.strict.equal(
uts46.toAscii('日本。co。jp', {
transitionalProcessing: true,
}),
'xn--wgv71a.co.jp',
);
assert.strict.equal(
uts46.toAscii('日本。co。jp', {
transitionalProcessing: false,
}),
'xn--wgv71a.co.jp',
);
// 日本。co.jp
assert.strict.equal(uts46.toUnicode('日本。co.jp'), '日本.co.jp');
assert.strict.equal(
uts46.toAscii('日本。co.jp', {
transitionalProcessing: true,
}),
'xn--wgv71a.co.jp',
);
assert.strict.equal(
uts46.toAscii('日本。co.jp', {
transitionalProcessing: false,
}),
'xn--wgv71a.co.jp',
);
// 日本⒈co.jp
assert.throws(function () {
uts46.toUnicode('日本⒈co.jp');
});
assert.throws(function () {
uts46.toAscii('日本⒈co.jp', {
transitionalProcessing: true,
});
});
assert.throws(function () {
uts46.toAscii('日本⒈co.jp', {
transitionalProcessing: false,
});
});
// x\u0327\u0301.de
assert.strict.equal(uts46.toUnicode('x\u0327\u0301.de'), 'x̧́.de');
assert.strict.equal(
uts46.toAscii('x\u0327\u0301.de', {
transitionalProcessing: true,
}),
'xn--x-xbb7i.de',
);
assert.strict.equal(
uts46.toAscii('x\u0327\u0301.de', {
transitionalProcessing: false,
}),
'xn--x-xbb7i.de',
);
// x\u0301\u0327.de
assert.strict.equal(uts46.toUnicode('x\u0301\u0327.de'), 'x̧́.de');
assert.strict.equal(
uts46.toAscii('x\u0301\u0327.de', {
transitionalProcessing: true,
}),
'xn--x-xbb7i.de',
);
assert.strict.equal(
uts46.toAscii('x\u0301\u0327.de', {
transitionalProcessing: false,
}),
'xn--x-xbb7i.de',
);
// σόλος.gr
assert.strict.equal(
uts46.toUnicode('σόλος.gr', {
transitionalProcessing: false,
}),
'σόλος.gr',
);
assert.strict.equal(
uts46.toAscii('σόλος.gr', {
transitionalProcessing: true,
}),
'xn--wxaikc6b.gr',
);
assert.strict.equal(
uts46.toAscii('σόλος.gr', {
transitionalProcessing: false,
}),
'xn--wxaijb9b.gr',
);
// Σόλος.gr
assert.strict.equal(
uts46.toUnicode('Σόλος.gr', {
transitionalProcessing: false,
}),
'σόλος.gr',
);
assert.strict.equal(
uts46.toAscii('Σόλος.gr', {
transitionalProcessing: true,
}),
'xn--wxaikc6b.gr',
);
assert.strict.equal(
uts46.toAscii('Σόλος.gr', {
transitionalProcessing: false,
}),
'xn--wxaijb9b.gr',
); // might be wrong
// ΣΌΛΟΣ.grﻋﺮﺑﻲ.de
assert.strict.equal(uts46.toUnicode('ΣΌΛΟΣ.grﻋﺮﺑﻲ.de'), 'σόλοσ.grعربي.de');
assert.strict.equal(
uts46.toAscii('ΣΌΛΟΣ.grﻋﺮﺑﻲ.de', {
transitionalProcessing: true,
}),
'xn--wxaikc6b.xn--gr-gtd9a1b0g.de',
);
assert.strict.equal(
uts46.toAscii('ΣΌΛΟΣ.grﻋﺮﺑﻲ.de', {
transitionalProcessing: false,
}),
'xn--wxaikc6b.xn--gr-gtd9a1b0g.de',
); // might be wrong
// عربي.de
assert.strict.equal(uts46.toUnicode('عربي.de'), 'عربي.de');
assert.strict.equal(
uts46.toAscii('عربي.de', {
transitionalProcessing: true,
}),
'xn--ngbrx4e.de',
);
assert.strict.equal(
uts46.toAscii('عربي.de', {
transitionalProcessing: false,
}),
'xn--ngbrx4e.de',
);
// نامهای.de
assert.strict.equal(uts46.toUnicode('نامهای.de'), 'نامهای.de');
assert.strict.equal(
uts46.toAscii('نامهای.de', {
transitionalProcessing: true,
}),
'xn--mgba3gch31f.de',
);
assert.strict.equal(
uts46.toAscii('نامهای.de', {
transitionalProcessing: false,
}),
'xn--mgba3gch31f.de',
);
// نامه\u200Cای.de
/* jshint -W100 */
assert.strict.equal(uts46.toUnicode('نامه\u200Cای.de'), 'نامهای.de');
assert.strict.equal(
uts46.toAscii('نامه\u200Cای.de', {
transitionalProcessing: true,
}),
'xn--mgba3gch31f.de',
);
assert.strict.equal(
uts46.toAscii('نامه\u200Cای.de', {
transitionalProcessing: false,
}),
'xn--mgba3gch31f060k.de',
);
/* jshint +W100 */
// common emojis
assert.strict.equal(uts46.toAscii('😂'), 'xn--g28h');
assert.strict.equal(uts46.toAscii('🫡'), 'xn--229h');
assert.strict.equal(uts46.toUnicode('xn--g28h'), '😂');
assert.strict.equal(uts46.toUnicode('xn--229h'), '🫡');
});
});