@@ -1735,4 +1735,119 @@ describe('PDFForm', () => {
17351735 expect ( retrievedFields ) . toEqual ( [ ] ) ;
17361736 } ) ;
17371737 } ) ;
1738+
1739+ describe ( 'PDFField.rename()' , ( ) => {
1740+ it ( 'can rename a root-level field' , async ( ) => {
1741+ const pdfDoc = await PDFDocument . create ( ) ;
1742+ const form = pdfDoc . getForm ( ) ;
1743+ const field = form . createTextField ( 'oldName' ) ;
1744+ field . setText ( 'test value' ) ;
1745+
1746+ expect ( field . getName ( ) ) . toBe ( 'oldName' ) ;
1747+ field . rename ( 'newName' ) ;
1748+ expect ( field . getName ( ) ) . toBe ( 'newName' ) ;
1749+ expect ( field . getText ( ) ) . toBe ( 'test value' ) ; // Value preserved
1750+ } ) ;
1751+
1752+ it ( 'can rename a nested field' , async ( ) => {
1753+ const pdfDoc = await PDFDocument . create ( ) ;
1754+ const form = pdfDoc . getForm ( ) ;
1755+ const field = form . createTextField ( 'person.name.first' ) ;
1756+
1757+ expect ( field . getName ( ) ) . toBe ( 'person.name.first' ) ;
1758+ field . rename ( 'given' ) ;
1759+ expect ( field . getName ( ) ) . toBe ( 'person.name.given' ) ;
1760+ } ) ;
1761+
1762+ it ( 'throws if new name contains a period' , async ( ) => {
1763+ const pdfDoc = await PDFDocument . create ( ) ;
1764+ const form = pdfDoc . getForm ( ) ;
1765+ const field = form . createTextField ( 'myField' ) ;
1766+
1767+ expect ( ( ) => field . rename ( 'new.name' ) ) . toThrow (
1768+ 'Field name contains invalid component' ,
1769+ ) ;
1770+ } ) ;
1771+
1772+ it ( 'throws if new name is empty' , async ( ) => {
1773+ const pdfDoc = await PDFDocument . create ( ) ;
1774+ const form = pdfDoc . getForm ( ) ;
1775+ const field = form . createTextField ( 'myField' ) ;
1776+
1777+ expect ( ( ) => field . rename ( '' ) ) . toThrow ( 'Field name must not be empty' ) ;
1778+ } ) ;
1779+
1780+ it ( 'throws if a sibling field already has the same name' , async ( ) => {
1781+ const pdfDoc = await PDFDocument . create ( ) ;
1782+ const form = pdfDoc . getForm ( ) ;
1783+ form . createTextField ( 'fieldA' ) ;
1784+ const fieldB = form . createTextField ( 'fieldB' ) ;
1785+
1786+ expect ( ( ) => fieldB . rename ( 'fieldA' ) ) . toThrow (
1787+ 'A field already exists with the specified name' ,
1788+ ) ;
1789+ } ) ;
1790+
1791+ it ( 'throws if renaming would conflict with nested sibling' , async ( ) => {
1792+ const pdfDoc = await PDFDocument . create ( ) ;
1793+ const form = pdfDoc . getForm ( ) ;
1794+ form . createTextField ( 'parent.child1' ) ;
1795+ const field = form . createTextField ( 'parent.child2' ) ;
1796+
1797+ expect ( ( ) => field . rename ( 'child1' ) ) . toThrow (
1798+ 'A field already exists with the specified name' ,
1799+ ) ;
1800+ } ) ;
1801+
1802+ it ( 'throws if renaming would conflict with a non-terminal field' , async ( ) => {
1803+ const pdfDoc = await PDFDocument . create ( ) ;
1804+ const form = pdfDoc . getForm ( ) ;
1805+ // Creates non-terminal 'person' containing terminal 'person.name'
1806+ form . createTextField ( 'person.name' ) ;
1807+ const field = form . createTextField ( 'otherField' ) ;
1808+
1809+ // Renaming to 'person' should fail because 'person' exists as non-terminal
1810+ expect ( ( ) => field . rename ( 'person' ) ) . toThrow (
1811+ 'A field already exists with the specified name' ,
1812+ ) ;
1813+ } ) ;
1814+
1815+ it ( 'no-ops if renaming to the same name' , async ( ) => {
1816+ const pdfDoc = await PDFDocument . create ( ) ;
1817+ const form = pdfDoc . getForm ( ) ;
1818+ const field = form . createTextField ( 'myField' ) ;
1819+
1820+ // Should not throw
1821+ field . rename ( 'myField' ) ;
1822+ expect ( field . getName ( ) ) . toBe ( 'myField' ) ;
1823+ } ) ;
1824+
1825+ it ( 'preserves field properties after rename' , async ( ) => {
1826+ const pdfDoc = await PDFDocument . create ( ) ;
1827+ const form = pdfDoc . getForm ( ) ;
1828+ const field = form . createTextField ( 'original' ) ;
1829+ field . setText ( 'Hello World' ) ;
1830+ field . enableReadOnly ( ) ;
1831+ field . enableRequired ( ) ;
1832+
1833+ field . rename ( 'renamed' ) ;
1834+
1835+ expect ( field . getName ( ) ) . toBe ( 'renamed' ) ;
1836+ expect ( field . getText ( ) ) . toBe ( 'Hello World' ) ;
1837+ expect ( field . isReadOnly ( ) ) . toBe ( true ) ;
1838+ expect ( field . isRequired ( ) ) . toBe ( true ) ;
1839+ } ) ;
1840+
1841+ it ( 'allows the renamed field to be retrieved by new name' , async ( ) => {
1842+ const pdfDoc = await PDFDocument . create ( ) ;
1843+ const form = pdfDoc . getForm ( ) ;
1844+ const field = form . createTextField ( 'oldName' ) ;
1845+
1846+ field . rename ( 'newName' ) ;
1847+
1848+ expect ( ( ) => form . getField ( 'oldName' ) ) . toThrow ( ) ;
1849+ // getField returns a new wrapper, so compare by ref
1850+ expect ( form . getField ( 'newName' ) . ref ) . toBe ( field . ref ) ;
1851+ } ) ;
1852+ } ) ;
17381853} ) ;
0 commit comments