Skip to content

Instantly share code, notes, and snippets.

@wangjohn
Last active October 28, 2024 18:35
Show Gist options
  • Select an option

  • Save wangjohn/418991f0dac46efdd7daab73a87c722b to your computer and use it in GitHub Desktop.

Select an option

Save wangjohn/418991f0dac46efdd7daab73a87c722b to your computer and use it in GitHub Desktop.
Example of generating typescript tests using Claude 3.5 Sonnet
Help me write a comprehensive set of unit tests in Typescript for the following function:
<function_to_test>
function romanToInt(roman: string): number {
const romanNumerals: { [key: string]: number } = {
'I': 1,
'V': 5,
'X': 10,
'L': 50,
'C': 100,
'D': 500,
'M': 1000,
};
let total = 0;
let prevValue = 0;
for (let i = roman.length - 1; i >= 0; i--) {
const currentChar = roman.charAt(i).toUpperCase();
const currentValue = romanNumerals[currentChar];
if (!currentValue) {
throw new Error(Invalid Roman numeral character: ${currentChar});
}
if (currentValue < prevValue) {
total -= currentValue;
} else {
total += currentValue;
prevValue = currentValue;
}
}
return total;
}
</function_to_test>
Please ensure that:
- The tests use the describe / expect pattern for typescript
- The tests follow typescript's testing best practices, including proper naming conventions and code organization.
- Use jest as the main testing framework
- Cover various scenarios, including normal cases, edge cases, and error handling.
We've provided a test example as an attached file.
describe('getDSTDetails', () => {
describe('when DST-related changes occur after midnight', () => {
it('returns a dstStart value if DST starts during the selected range', () => {
const mar_1_2024 = DateTime.fromObject(
{
day: 1,
month: 3,
year: 2024,
hour: 0,
minute: 0,
second: 0,
},
{
zone: TIMEZONE_LOS_ANGELES,
}
);
const nov_2_2024 = DateTime.fromObject(
{
day: 2,
month: 11,
year: 2024,
hour: 0,
minute: 0,
second: 0,
},
{
zone: TIMEZONE_LOS_ANGELES,
}
);
const details = getDSTDetails(mar_1_2024, nov_2_2024, TIMEZONE_LOS_ANGELES);
expect(details?.dstStart?.toISODate()).toBe('2024-03-10');
expect(details?.dstEnd).toBeUndefined();
});
it('returns a dstEnd if DST ends during the selected range', () => {
const nov_1_2023 = DateTime.fromObject(
{
day: 1,
month: 11,
year: 2023,
hour: 0,
minute: 0,
second: 0,
},
{
zone: TIMEZONE_LOS_ANGELES,
}
);
const mar_9_2024 = DateTime.fromObject(
{
day: 9,
month: 3,
year: 2024,
hour: 0,
minute: 0,
second: 0,
},
{
zone: TIMEZONE_LOS_ANGELES,
}
);
const details = getDSTDetails(nov_1_2023, mar_9_2024, TIMEZONE_LOS_ANGELES);
expect(details?.dstEnd?.toISODate()).toBe('2023-11-05');
expect(details?.dstStart).toBeUndefined();
});
it('returns both a dstStart and dstEnd value for date ranges containing the start and end of DST', () => {
const jan_1_2023 = DateTime.fromObject(
{
day: 1,
month: 1,
year: 2023,
hour: 0,
minute: 0,
second: 0,
},
{
zone: TIMEZONE_LOS_ANGELES,
}
);
const dec_31_2023 = DateTime.fromObject(
{
day: 31,
month: 12,
year: 2023,
hour: 0,
minute: 0,
second: 0,
},
{
zone: TIMEZONE_LOS_ANGELES,
}
);
const details = getDSTDetails(jan_1_2023, dec_31_2023, TIMEZONE_LOS_ANGELES);
expect(details?.dstStart?.toISODate()).toBe('2023-03-12');
expect(details?.dstEnd?.toISODate()).toBe('2023-11-05');
});
it('returns both a dstStart and dstEnd value for date ranges containing the start and end of DST in different years', () => {
const nov_1_2023 = DateTime.fromObject(
{
day: 1,
month: 1,
year: 2023,
hour: 0,
minute: 0,
second: 0,
},
{
zone: TIMEZONE_LOS_ANGELES,
}
);
const mar_31_2024 = DateTime.fromObject(
{
day: 31,
month: 3,
year: 2024,
hour: 0,
minute: 0,
second: 0,
},
{
zone: TIMEZONE_LOS_ANGELES,
}
);
const details = getDSTDetails(nov_1_2023, mar_31_2024, TIMEZONE_LOS_ANGELES);
expect(details?.dstStart?.toISODate()).toBe('2024-03-10');
expect(details?.dstEnd?.toISODate()).toBe('2023-11-05');
});
});
describe('when DST-related changes occur at midnight', () => {
it('returns true if DST starts during the selected range', () => {
const sep_1_2023 = DateTime.fromObject(
{
day: 1,
month: 8,
year: 2023,
hour: 0,
minute: 0,
second: 0,
},
{
zone: TIMEZONE_SANTIAGO,
}
);
const apr_5_2024 = DateTime.fromObject(
{
day: 5,
month: 4,
year: 2024,
hour: 0,
minute: 0,
second: 0,
},
{
zone: TIMEZONE_SANTIAGO,
}
);
const details = getDSTDetails(sep_1_2023, apr_5_2024, TIMEZONE_SANTIAGO);
expect(details?.dstStart?.toISODate()).toBe('2023-09-02');
expect(details?.dstEnd).toBeUndefined();
});
it('returns true if DST ends during the selected range', () => {
const apr_1_2024 = DateTime.fromObject(
{
day: 1,
month: 4,
year: 2024,
hour: 0,
minute: 0,
second: 0,
},
{
zone: 'America/Santiago',
}
);
const sep_6_2024 = DateTime.fromObject(
{
day: 6,
month: 8,
year: 2024,
hour: 0,
minute: 0,
second: 0,
},
{
zone: TIMEZONE_SANTIAGO,
}
);
const details = getDSTDetails(apr_1_2024, sep_6_2024, TIMEZONE_SANTIAGO);
expect(details?.dstEnd?.toISODate()).toBe('2024-04-06');
expect(details?.dstStart).toBeUndefined();
});
it('returns true for date ranges containing the start and end of DST in the same year', () => {
const jan_1_2023 = DateTime.fromObject(
{
day: 1,
month: 1,
year: 2023,
hour: 0,
minute: 0,
second: 0,
},
{
zone: TIMEZONE_SANTIAGO,
}
);
const dec_31_2023 = DateTime.fromObject(
{
day: 31,
month: 12,
year: 2023,
hour: 0,
minute: 0,
second: 0,
},
{
zone: TIMEZONE_SANTIAGO,
}
);
const details = getDSTDetails(jan_1_2023, dec_31_2023, TIMEZONE_SANTIAGO);
expect(details?.dstStart?.toISODate()).toBe('2023-09-02');
expect(details?.dstEnd?.toISODate()).toBe('2023-04-01');
});
it('returns true for date ranges containing the start and end of DST in different years', () => {
const sep_1_2023 = DateTime.fromObject(
{
day: 1,
month: 9,
year: 2023,
hour: 0,
minute: 0,
second: 0,
},
{
zone: TIMEZONE_SANTIAGO,
}
);
const apr_30_2024 = DateTime.fromObject(
{
day: 30,
month: 4,
year: 2024,
hour: 0,
minute: 0,
second: 0,
},
{
zone: TIMEZONE_SANTIAGO,
}
);
const details = getDSTDetails(sep_1_2023, apr_30_2024, TIMEZONE_SANTIAGO);
expect(details?.dstStart?.toISODate()).toBe('2023-09-02');
expect(details?.dstEnd?.toISODate()).toBe('2024-04-06');
});
});
it('returns undefined when no DST-related changes occur during the given date range', () => {
expect(
getDSTDetails(
DateTime.fromObject(
{
day: 8,
month: 4,
year: 2024,
hour: 0,
minute: 0,
second: 0,
},
{
zone: TIMEZONE_SANTIAGO,
}
),
DateTime.fromObject(
{
day: 7,
month: 9,
year: 2024,
hour: 0,
minute: 0,
second: 0,
},
{
zone: TIMEZONE_SANTIAGO,
}
),
TIMEZONE_SANTIAGO
)
).toBeUndefined();
expect(
getDSTDetails(
DateTime.fromObject(
{
day: 6,
month: 11,
year: 2023,
hour: 0,
minute: 0,
second: 0,
},
{
zone: TIMEZONE_LOS_ANGELES,
}
),
DateTime.fromObject(
{
day: 9,
month: 3,
year: 2024,
hour: 0,
minute: 0,
second: 0,
},
{
zone: TIMEZONE_LOS_ANGELES,
}
),
TIMEZONE_LOS_ANGELES
)
).toBeUndefined();
expect(
getDSTDetails(
DateTime.fromObject(
{
day: 1,
month: 1,
year: 2024,
hour: 0,
minute: 0,
second: 0,
},
{
zone: TIMEZONE_TOKYO,
}
),
DateTime.fromObject(
{
day: 31,
month: 12,
year: 2024,
hour: 0,
minute: 0,
second: 0,
},
{
zone: TIMEZONE_TOKYO,
}
),
TIMEZONE_TOKYO
)
).toBeUndefined();
});
});
import { describe, expect, it } from '@jest/globals';
describe('romanToInt', () => {
describe('basic Roman numeral conversions', () => {
it('converts single-character Roman numerals correctly', () => {
expect(romanToInt('I')).toBe(1);
expect(romanToInt('V')).toBe(5);
expect(romanToInt('X')).toBe(10);
expect(romanToInt('L')).toBe(50);
expect(romanToInt('C')).toBe(100);
expect(romanToInt('D')).toBe(500);
expect(romanToInt('M')).toBe(1000);
});
it('converts basic multi-character Roman numerals correctly', () => {
expect(romanToInt('II')).toBe(2);
expect(romanToInt('III')).toBe(3);
expect(romanToInt('XX')).toBe(20);
expect(romanToInt('XXX')).toBe(30);
expect(romanToInt('CC')).toBe(200);
expect(romanToInt('MMM')).toBe(3000);
});
it('handles subtractive notation correctly', () => {
expect(romanToInt('IV')).toBe(4);
expect(romanToInt('IX')).toBe(9);
expect(romanToInt('XL')).toBe(40);
expect(romanToInt('XC')).toBe(90);
expect(romanToInt('CD')).toBe(400);
expect(romanToInt('CM')).toBe(900);
});
it('converts complex Roman numerals correctly', () => {
expect(romanToInt('XXXIX')).toBe(39);
expect(romanToInt('CCXLVI')).toBe(246);
expect(romanToInt('DCCLXXXIX')).toBe(789);
expect(romanToInt('MMCDXXI')).toBe(2421);
expect(romanToInt('MMMCMXCIX')).toBe(3999);
});
});
describe('edge cases and input variations', () => {
it('handles lowercase Roman numerals correctly', () => {
expect(romanToInt('iv')).toBe(4);
expect(romanToInt('xii')).toBe(12);
expect(romanToInt('mcmliv')).toBe(1954);
});
it('handles mixed case Roman numerals correctly', () => {
expect(romanToInt('XiV')).toBe(14);
expect(romanToInt('mCmXcIx')).toBe(1999);
});
it('handles single character input correctly', () => {
expect(romanToInt('i')).toBe(1);
expect(romanToInt('v')).toBe(5);
});
it('processes empty string input appropriately', () => {
expect(() => romanToInt('')).toThrow('Invalid Roman numeral character: ');
});
});
describe('error handling', () => {
it('throws error for invalid Roman numeral characters', () => {
expect(() => romanToInt('A')).toThrow('Invalid Roman numeral character: A');
expect(() => romanToInt('E')).toThrow('Invalid Roman numeral character: E');
expect(() => romanToInt('B')).toThrow('Invalid Roman numeral character: B');
expect(() => romanToInt('Z')).toThrow('Invalid Roman numeral character: Z');
});
it('throws error for non-alphabetic characters', () => {
expect(() => romanToInt('X1X')).toThrow('Invalid Roman numeral character: 1');
expect(() => romanToInt('VI!')).toThrow('Invalid Roman numeral character: !');
expect(() => romanToInt('IX ')).toThrow('Invalid Roman numeral character: ');
});
it('throws error for invalid mixed input', () => {
expect(() => romanToInt('X#IV')).toThrow('Invalid Roman numeral character: #');
expect(() => romanToInt('VI@I')).toThrow('Invalid Roman numeral character: @');
});
});
describe('boundary cases', () => {
it('handles maximum valid Roman numeral values', () => {
// Maximum value typically represented in Roman numerals is 3999 (MMMCMXCIX)
expect(romanToInt('MMMCMXCIX')).toBe(3999);
});
it('handles minimum valid Roman numeral values', () => {
expect(romanToInt('I')).toBe(1);
});
it('processes repeated valid numerals correctly', () => {
expect(romanToInt('III')).toBe(3);
expect(romanToInt('XXX')).toBe(30);
expect(romanToInt('CCC')).toBe(300);
expect(romanToInt('MMM')).toBe(3000);
});
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment