mirror of
https://github.com/selfxyz/self.git
synced 2026-01-14 09:08:03 -05:00
435 lines
16 KiB
TypeScript
435 lines
16 KiB
TypeScript
import { expect } from "chai";
|
|
import { ethers } from "hardhat";
|
|
import { TestFormatter } from "../../typechain-types";
|
|
import { Formatter } from "../utils/formatter";
|
|
import { BigNumberish } from "ethers";
|
|
|
|
describe("Formatter", function () {
|
|
let testFormatter: TestFormatter;
|
|
|
|
before(async function () {
|
|
const TestFormatterFactory = await ethers.getContractFactory("TestFormatter");
|
|
testFormatter = await TestFormatterFactory.deploy();
|
|
await testFormatter.waitForDeployment();
|
|
});
|
|
|
|
describe("formatName", function () {
|
|
it("should match contract and ts implementation", async function () {
|
|
const input = "DUPONT<<ALPHONSE<HUGHUES<ALBERT<<<";
|
|
const contractResult = await testFormatter.testFormatName(input);
|
|
const tsResult = Formatter.formatName(input);
|
|
expect(contractResult[0]).to.equal(tsResult[0]);
|
|
expect(contractResult[1]).to.equal(tsResult[1]);
|
|
expect(contractResult[0]).to.equal("ALPHONSE HUGHUES ALBERT");
|
|
expect(contractResult[1]).to.equal("DUPONT");
|
|
});
|
|
|
|
it("should match contract and ts implementation for single name", async function () {
|
|
const input = "SMITH<<JOHN<<<";
|
|
const contractResult = await testFormatter.testFormatName(input);
|
|
const tsResult = Formatter.formatName(input);
|
|
expect(contractResult[0]).to.equal(tsResult[0]);
|
|
expect(contractResult[1]).to.equal(tsResult[1]);
|
|
expect(contractResult[0]).to.equal("JOHN");
|
|
expect(contractResult[1]).to.equal("SMITH");
|
|
});
|
|
});
|
|
|
|
describe("formatDate", function () {
|
|
it("should match contract and ts implementation", async function () {
|
|
const input = "940131";
|
|
const contractResult = await testFormatter.testFormatDate(input);
|
|
const tsResult = Formatter.formatDate(input);
|
|
expect(contractResult).to.equal(tsResult);
|
|
expect(contractResult).to.equal("31-01-94");
|
|
});
|
|
|
|
it("should handle errors consistently between contract and ts", async function () {
|
|
const input = "12345";
|
|
await expect(testFormatter.testFormatDate(input)).to.be.revertedWithCustomError(
|
|
testFormatter,
|
|
"InvalidDateLength",
|
|
);
|
|
expect(() => Formatter.formatDate(input)).to.throw("InvalidDateLength");
|
|
});
|
|
|
|
it("should handle errors consistently when month is out of range", async function () {
|
|
const input = "941331";
|
|
await expect(testFormatter.testFormatDate(input)).to.be.revertedWithCustomError(
|
|
testFormatter,
|
|
"InvalidMonthRange",
|
|
);
|
|
expect(() => Formatter.formatDate(input)).to.throw("InvalidMonthRange");
|
|
});
|
|
|
|
it("should handle errors consistently when month is out of range (more than 20)", async function () {
|
|
const input = "942032";
|
|
await expect(testFormatter.testFormatDate(input)).to.be.revertedWithCustomError(
|
|
testFormatter,
|
|
"InvalidMonthRange",
|
|
);
|
|
expect(() => Formatter.formatDate(input)).to.throw("InvalidMonthRange");
|
|
});
|
|
|
|
it("should handle errors consistently when day is out of range (more than 31)", async function () {
|
|
const input = "940132";
|
|
await expect(testFormatter.testFormatDate(input)).to.be.revertedWithCustomError(testFormatter, "InvalidDayRange");
|
|
expect(() => Formatter.formatDate(input)).to.throw("InvalidDayRange");
|
|
});
|
|
|
|
it("should handle errors consistently when day is out of range (more than 40)", async function () {
|
|
const input = "940140";
|
|
await expect(testFormatter.testFormatDate(input)).to.be.revertedWithCustomError(testFormatter, "InvalidDayRange");
|
|
expect(() => Formatter.formatDate(input)).to.throw("InvalidDayRange");
|
|
});
|
|
});
|
|
|
|
describe("numAsciiToUint", function () {
|
|
it("should match contract and ts implementation for valid ASCII numbers", async function () {
|
|
for (let i = 0; i <= 9; i++) {
|
|
const input = 48 + i;
|
|
const contractResult = await testFormatter.testNumAsciiToUint(input);
|
|
const tsResult = Formatter.numAsciiToUint(input);
|
|
expect(contractResult).to.equal(tsResult);
|
|
expect(contractResult).to.equal(i);
|
|
}
|
|
});
|
|
});
|
|
|
|
describe("fieldElementsToBytes", function () {
|
|
it("should match contract and ts implementation", async function () {
|
|
const input: [BigNumberish, BigNumberish, BigNumberish] = [123n, 456n, 789n];
|
|
const contractResult = await testFormatter.testFieldElementsToBytes(input);
|
|
const tsResult = toHexString(Formatter.fieldElementsToBytes(input as [bigint, bigint, bigint]));
|
|
expect(contractResult).to.deep.equal(tsResult);
|
|
});
|
|
|
|
it("should match contract and ts implementation for zero values", async function () {
|
|
const input: [BigNumberish, BigNumberish, BigNumberish] = [0n, 0n, 0n];
|
|
const contractResult = await testFormatter.testFieldElementsToBytes(input);
|
|
const tsResult = toHexString(Formatter.fieldElementsToBytes(input as [bigint, bigint, bigint]));
|
|
expect(contractResult).to.deep.equal(tsResult);
|
|
});
|
|
|
|
it("should revert when field element is out of range", async function () {
|
|
const input = [21888242871839275222246405745257275088548364400416034343698204186575808495617n, 0n, 0n] as [
|
|
bigint,
|
|
bigint,
|
|
bigint,
|
|
];
|
|
await expect(testFormatter.testFieldElementsToBytes(input)).to.be.revertedWithCustomError(
|
|
testFormatter,
|
|
"InvalidFieldElement",
|
|
);
|
|
});
|
|
|
|
it("should revert when field element is out of range", async function () {
|
|
const input = [0n, 21888242871839275222246405745257275088548364400416034343698204186575808495617n, 0n] as [
|
|
bigint,
|
|
bigint,
|
|
bigint,
|
|
];
|
|
await expect(testFormatter.testFieldElementsToBytes(input)).to.be.revertedWithCustomError(
|
|
testFormatter,
|
|
"InvalidFieldElement",
|
|
);
|
|
});
|
|
|
|
it("should revert when field element is out of range", async function () {
|
|
const input = [0n, 0n, 21888242871839275222246405745257275088548364400416034343698204186575808495617n] as [
|
|
bigint,
|
|
bigint,
|
|
bigint,
|
|
];
|
|
await expect(testFormatter.testFieldElementsToBytes(input)).to.be.revertedWithCustomError(
|
|
testFormatter,
|
|
"InvalidFieldElement",
|
|
);
|
|
});
|
|
});
|
|
|
|
describe("extractForbiddenCountriesFromPacked", function () {
|
|
it("should match contract and ts implementation", async function () {
|
|
const input1 = "0x414754414154414149414f4741444e414d5341415a44424c41414c41474641";
|
|
const input2 = "0x4542524c42425242444742524842534842455a415355415742414d52414752";
|
|
const input3 = "0x4e41434d484b5650434e52424c4f424e5442554d424e45425a4c42554d424c";
|
|
const input4 = "0x4853454d4559424d5a45575a5455564b4e445453454e4843564943";
|
|
const contractResult = await testFormatter.testExtractForbiddenCountriesFromPacked([
|
|
input1,
|
|
input2,
|
|
input3,
|
|
input4,
|
|
]);
|
|
const tsResult: string[] = Formatter.extractForbiddenCountriesFromPacked([input1, input2, input3, input4], "id");
|
|
let formattedTsResult = tsResult
|
|
.map((item: string, index: number) => {
|
|
if (index % 3 === 0) {
|
|
return item + tsResult[index + 1] + tsResult[index + 2];
|
|
}
|
|
return undefined;
|
|
})
|
|
.filter(Boolean);
|
|
expect(contractResult).to.deep.equal(formattedTsResult);
|
|
});
|
|
|
|
it("should revert when field element is out of range", async function () {
|
|
const input = 21888242871839275222246405745257275088548364400416034343698204186575808495617n;
|
|
|
|
await expect(
|
|
testFormatter.testExtractForbiddenCountriesFromPacked([input, 0n, 0n, 0n]),
|
|
).to.be.revertedWithCustomError(testFormatter, "InvalidFieldElement");
|
|
});
|
|
});
|
|
|
|
describe("proofDateToUnixTimestamp", function () {
|
|
it("should match contract and ts implementation", async function () {
|
|
const testCases = [
|
|
{
|
|
input: [9, 4, 0, 1, 3, 1],
|
|
expected: 3915734400n,
|
|
},
|
|
{
|
|
input: [0, 0, 0, 1, 0, 1],
|
|
expected: 946684800n,
|
|
},
|
|
{
|
|
input: [2, 0, 0, 2, 2, 9],
|
|
expected: 1582934400n,
|
|
},
|
|
];
|
|
|
|
for (const testCase of testCases) {
|
|
const contractResult = await testFormatter.testProofDateToUnixTimestamp(testCase.input);
|
|
const tsResult = Formatter.proofDateToUnixTimestamp(testCase.input);
|
|
expect(contractResult).to.equal(BigInt(tsResult));
|
|
expect(contractResult).to.equal(testCase.expected);
|
|
}
|
|
});
|
|
|
|
it("should revert when date digit is out of range", async function () {
|
|
const input = [9, 4, 0, 1, 2, 10];
|
|
await expect(testFormatter.testProofDateToUnixTimestamp(input)).to.be.revertedWithCustomError(
|
|
testFormatter,
|
|
"InvalidDateDigit",
|
|
);
|
|
});
|
|
});
|
|
|
|
describe("dateToUnixTimestamp", function () {
|
|
it("should match contract and ts implementation", async function () {
|
|
const testCases = [
|
|
{
|
|
input: "940131",
|
|
expected: 3915734400n,
|
|
},
|
|
{
|
|
input: "000101",
|
|
expected: 946684800n,
|
|
},
|
|
];
|
|
|
|
for (const testCase of testCases) {
|
|
const contractResult = await testFormatter.testDateToUnixTimestamp(testCase.input);
|
|
const tsResult = Formatter.dateToUnixTimestamp(testCase.input);
|
|
expect(contractResult).to.equal(BigInt(tsResult));
|
|
expect(contractResult).to.equal(testCase.expected);
|
|
}
|
|
});
|
|
|
|
it("should handle errors consistently between contract and ts", async function () {
|
|
const input = "12345";
|
|
await expect(testFormatter.testDateToUnixTimestamp(input)).to.be.revertedWithCustomError(
|
|
testFormatter,
|
|
"InvalidDateLength",
|
|
);
|
|
expect(() => Formatter.dateToUnixTimestamp(input)).to.throw("InvalidDateLength");
|
|
});
|
|
|
|
it("should revert when month is out of range (more than 12)", async function () {
|
|
const input = "941331";
|
|
await expect(testFormatter.testDateToUnixTimestamp(input)).to.be.revertedWithCustomError(
|
|
testFormatter,
|
|
"InvalidMonthRange",
|
|
);
|
|
});
|
|
|
|
it("should revert when month is out of range (more than 20)", async function () {
|
|
const input = "942031";
|
|
await expect(testFormatter.testDateToUnixTimestamp(input)).to.be.revertedWithCustomError(
|
|
testFormatter,
|
|
"InvalidMonthRange",
|
|
);
|
|
});
|
|
|
|
it("should revert when day is out of range (more than 31)", async function () {
|
|
const input = "940132";
|
|
await expect(testFormatter.testDateToUnixTimestamp(input)).to.be.revertedWithCustomError(
|
|
testFormatter,
|
|
"InvalidDayRange",
|
|
);
|
|
});
|
|
|
|
it("should revert when day is out of range (more than 40)", async function () {
|
|
const input = "940140";
|
|
await expect(testFormatter.testDateToUnixTimestamp(input)).to.be.revertedWithCustomError(
|
|
testFormatter,
|
|
"InvalidDayRange",
|
|
);
|
|
});
|
|
});
|
|
|
|
describe("substring", function () {
|
|
it("should match contract and ts implementation", async function () {
|
|
const testCases = [
|
|
{ str: "ABCDEF", start: 0, end: 3, expected: "ABC" },
|
|
{ str: "ABCDEF", start: 2, end: 4, expected: "CD" },
|
|
{ str: "ABCDEF", start: 0, end: 6, expected: "ABCDEF" },
|
|
];
|
|
|
|
for (const testCase of testCases) {
|
|
const contractResult = await testFormatter.testSubstring(testCase.str, testCase.start, testCase.end);
|
|
const tsResult = Formatter.substring(testCase.str, testCase.start, testCase.end);
|
|
expect(contractResult).to.equal(tsResult);
|
|
expect(contractResult).to.equal(testCase.expected);
|
|
}
|
|
});
|
|
});
|
|
|
|
describe("parseDatePart", function () {
|
|
it("should match contract and ts implementation", async function () {
|
|
const testCases = [
|
|
{ input: "12", expected: 12 },
|
|
{ input: "01", expected: 1 },
|
|
{ input: "00", expected: 0 },
|
|
{ input: "", expected: 0 },
|
|
];
|
|
|
|
for (const testCase of testCases) {
|
|
const contractResult = await testFormatter.testParseDatePart(testCase.input);
|
|
const tsResult = Formatter.parseDatePart(testCase.input);
|
|
expect(contractResult).to.equal(tsResult);
|
|
expect(contractResult).to.equal(testCase.expected);
|
|
}
|
|
});
|
|
});
|
|
|
|
describe("toTimestamp", function () {
|
|
it("should match contract and ts implementation", async function () {
|
|
const testCases = [
|
|
{
|
|
year: 2000,
|
|
month: 1,
|
|
day: 1,
|
|
expected: 946684800n,
|
|
},
|
|
{
|
|
year: 2020,
|
|
month: 2,
|
|
day: 29,
|
|
expected: 1582934400n,
|
|
},
|
|
];
|
|
|
|
for (const testCase of testCases) {
|
|
const contractResult = await testFormatter.testToTimestamp(testCase.year, testCase.month, testCase.day);
|
|
const tsResult = Formatter.toTimestamp(testCase.year, testCase.month, testCase.day);
|
|
expect(contractResult).to.equal(BigInt(tsResult));
|
|
expect(contractResult).to.equal(testCase.expected);
|
|
}
|
|
});
|
|
|
|
it("should revert when year is out of range", async function () {
|
|
const input = 1969;
|
|
await expect(testFormatter.testToTimestamp(input, 1, 1)).to.be.revertedWithCustomError(
|
|
testFormatter,
|
|
"InvalidYearRange",
|
|
);
|
|
});
|
|
|
|
it("should revert when year is out of range", async function () {
|
|
const input = 2101;
|
|
await expect(testFormatter.testToTimestamp(input, 1, 1)).to.be.revertedWithCustomError(
|
|
testFormatter,
|
|
"InvalidYearRange",
|
|
);
|
|
});
|
|
|
|
it("should revert when month is out of range", async function () {
|
|
const input = 13;
|
|
await expect(testFormatter.testToTimestamp(2000, input, 1)).to.be.revertedWithCustomError(
|
|
testFormatter,
|
|
"InvalidMonthRange",
|
|
);
|
|
});
|
|
|
|
it("should revert when month is out of range", async function () {
|
|
const input = 0;
|
|
await expect(testFormatter.testToTimestamp(2000, input, 1)).to.be.revertedWithCustomError(
|
|
testFormatter,
|
|
"InvalidMonthRange",
|
|
);
|
|
});
|
|
|
|
it("should revert when day is out of range", async function () {
|
|
const input = 32;
|
|
await expect(testFormatter.testToTimestamp(2000, 1, input)).to.be.revertedWithCustomError(
|
|
testFormatter,
|
|
"InvalidDayRange",
|
|
);
|
|
});
|
|
|
|
it("should revert when day is out of range", async function () {
|
|
const input = 0;
|
|
await expect(testFormatter.testToTimestamp(2000, 1, input)).to.be.revertedWithCustomError(
|
|
testFormatter,
|
|
"InvalidDayRange",
|
|
);
|
|
});
|
|
});
|
|
|
|
describe("isLeapYear", function () {
|
|
it("should match contract and ts implementation", async function () {
|
|
const testCases = [
|
|
{ year: 2000, expected: true },
|
|
{ year: 2020, expected: true },
|
|
{ year: 2001, expected: false },
|
|
{ year: 2042, expected: false },
|
|
{ year: 2100, expected: false },
|
|
{ year: 1970, expected: false },
|
|
];
|
|
|
|
for (const testCase of testCases) {
|
|
const contractResult = await testFormatter.testIsLeapYear(testCase.year);
|
|
const tsResult = Formatter.isLeapYear(testCase.year);
|
|
expect(contractResult).to.equal(tsResult);
|
|
expect(contractResult).to.equal(testCase.expected);
|
|
}
|
|
});
|
|
|
|
it("should revert when year is out of range", async function () {
|
|
const input = 1969;
|
|
await expect(testFormatter.testIsLeapYear(input)).to.be.revertedWithCustomError(
|
|
testFormatter,
|
|
"InvalidYearRange",
|
|
);
|
|
});
|
|
|
|
it("should revert when year is out of range", async function () {
|
|
const input = 2101;
|
|
await expect(testFormatter.testIsLeapYear(input)).to.be.revertedWithCustomError(
|
|
testFormatter,
|
|
"InvalidYearRange",
|
|
);
|
|
});
|
|
});
|
|
});
|
|
|
|
function toHexString(bytes: Uint8Array): string {
|
|
return (
|
|
"0x" +
|
|
Array.from(bytes)
|
|
.map((b) => b.toString(16).padStart(2, "0"))
|
|
.join("")
|
|
);
|
|
}
|