Last active
October 28, 2024 18:35
-
-
Save wangjohn/418991f0dac46efdd7daab73a87c722b to your computer and use it in GitHub Desktop.
Example of generating typescript tests using Claude 3.5 Sonnet
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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(); | |
| }); | |
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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