xfa_tohtml_spec.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649
  1. /* Copyright 2020 Mozilla Foundation
  2. *
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. import { isNodeJS } from "../../src/shared/is_node.js";
  16. import { XFAFactory } from "../../src/core/xfa/factory.js";
  17. describe("XFAFactory", function () {
  18. function searchHtmlNode(root, name, value, byAttributes = false, nth = [0]) {
  19. if (
  20. (!byAttributes && root[name] === value) ||
  21. (byAttributes && root.attributes && root.attributes[name] === value)
  22. ) {
  23. if (nth[0]-- === 0) {
  24. return root;
  25. }
  26. }
  27. if (!root.children) {
  28. return null;
  29. }
  30. for (const child of root.children) {
  31. const node = searchHtmlNode(child, name, value, byAttributes, nth);
  32. if (node) {
  33. return node;
  34. }
  35. }
  36. return null;
  37. }
  38. describe("toHTML", function () {
  39. it("should convert some basic properties to CSS", async () => {
  40. const xml = `
  41. <?xml version="1.0"?>
  42. <xdp:xdp xmlns:xdp="http://ns.adobe.com/xdp/">
  43. <template xmlns="http://www.xfa.org/schema/xfa-template/3.3">
  44. <subform name="root" mergeMode="matchTemplate">
  45. <pageSet>
  46. <pageArea>
  47. <contentArea x="123pt" w="456pt" h="789pt"/>
  48. <medium stock="default" short="456pt" long="789pt"/>
  49. <draw y="1pt" w="11pt" h="22pt" rotate="90" x="2pt">
  50. <assist><toolTip>A tooltip !!</toolTip></assist>
  51. <font size="7pt" typeface="FooBar" baselineShift="2pt">
  52. <fill>
  53. <color value="12,23,34"/>
  54. <solid/>
  55. </fill>
  56. </font>
  57. <value/>
  58. <margin topInset="1pt" bottomInset="2pt" leftInset="3pt" rightInset="4pt"/>
  59. <para spaceAbove="1pt" spaceBelow="2pt" textIndent="3pt" marginLeft="4pt" marginRight="5pt"/>
  60. </draw>
  61. </pageArea>
  62. </pageSet>
  63. <subform name="second">
  64. <breakBefore targetType="pageArea" startNew="1"/>
  65. <subform>
  66. <draw w="1pt" h="1pt"><value><text>foo</text></value></draw>
  67. </subform>
  68. </subform>
  69. <subform name="third">
  70. <breakBefore targetType="pageArea" startNew="1"/>
  71. <subform>
  72. <draw w="1pt" h="1pt"><value><text>bar</text></value></draw>
  73. </subform>
  74. </subform>
  75. </subform>
  76. </template>
  77. <xfa:datasets xmlns:xfa="http://www.xfa.org/schema/xfa-data/1.0/">
  78. <xfa:data>
  79. </xfa:data>
  80. </xfa:datasets>
  81. </xdp:xdp>
  82. `;
  83. const factory = new XFAFactory({ "xdp:xdp": xml });
  84. factory.setFonts([]);
  85. expect(await factory.getNumPages()).toEqual(2);
  86. const pages = await factory.getPages();
  87. const page1 = pages.children[0];
  88. expect(page1.attributes.style).toEqual({
  89. height: "789px",
  90. width: "456px",
  91. });
  92. expect(page1.children.length).toEqual(2);
  93. const container = page1.children[1];
  94. expect(container.attributes.class).toEqual(["xfaContentarea"]);
  95. expect(container.attributes.style).toEqual({
  96. height: "789px",
  97. width: "456px",
  98. left: "123px",
  99. top: "0px",
  100. });
  101. const wrapper = page1.children[0];
  102. const draw = wrapper.children[0];
  103. expect(wrapper.attributes.class).toEqual(["xfaWrapper"]);
  104. expect(wrapper.attributes.style).toEqual({
  105. alignSelf: "start",
  106. height: "22px",
  107. left: "2px",
  108. position: "absolute",
  109. top: "1px",
  110. transform: "rotate(-90deg)",
  111. transformOrigin: "top left",
  112. width: "11px",
  113. });
  114. expect(draw.attributes.class).toEqual([
  115. "xfaDraw",
  116. "xfaFont",
  117. "xfaWrapped",
  118. ]);
  119. expect(draw.attributes.title).toEqual("A tooltip !!");
  120. expect(draw.attributes.style).toEqual({
  121. color: "#0c1722",
  122. fontFamily: '"FooBar"',
  123. fontKerning: "none",
  124. letterSpacing: "0px",
  125. fontStyle: "normal",
  126. fontWeight: "normal",
  127. fontSize: "6.93px",
  128. padding: "1px 4px 2px 3px",
  129. verticalAlign: "2px",
  130. });
  131. // draw element must be on each page.
  132. expect(draw.attributes.style).toEqual(
  133. pages.children[1].children[0].children[0].attributes.style
  134. );
  135. });
  136. it("should have an alt attribute from toolTip", async () => {
  137. if (isNodeJS) {
  138. pending("Image is not supported in Node.js.");
  139. }
  140. const xml = `
  141. <?xml version="1.0"?>
  142. <xdp:xdp xmlns:xdp="http://ns.adobe.com/xdp/">
  143. <template xmlns="http://www.xfa.org/schema/xfa-template/3.3">
  144. <subform name="root" mergeMode="matchTemplate">
  145. <pageSet>
  146. <pageArea>
  147. <contentArea x="0pt" w="456pt" h="789pt"/>
  148. <draw name="BA-Logo" y="5.928mm" x="128.388mm" w="71.237mm" h="9.528mm">
  149. <value>
  150. <image contentType="image/png">iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVQYV2NgYAAAAAMAAWgmWQ0AAAAASUVORK5CYII=</image>
  151. </value>
  152. <assist><toolTip>alt text</toolTip></assist>
  153. </draw>
  154. </pageArea>
  155. </pageSet>
  156. </subform>
  157. </template>
  158. <xfa:datasets xmlns:xfa="http://www.xfa.org/schema/xfa-data/1.0/">
  159. <xfa:data>
  160. </xfa:data>
  161. </xfa:datasets>
  162. </xdp:xdp>
  163. `;
  164. const factory = new XFAFactory({ "xdp:xdp": xml });
  165. expect(await factory.getNumPages()).toEqual(1);
  166. const pages = await factory.getPages();
  167. const field = searchHtmlNode(pages, "name", "img");
  168. expect(field.attributes.alt).toEqual("alt text");
  169. });
  170. it("should have a aria heading role and level", async () => {
  171. const xml = `
  172. <?xml version="1.0"?>
  173. <xdp:xdp xmlns:xdp="http://ns.adobe.com/xdp/">
  174. <template xmlns="http://www.xfa.org/schema/xfa-template/3.3">
  175. <subform name="root" mergeMode="matchTemplate">
  176. <pageSet>
  177. <pageArea>
  178. <contentArea x="0pt" w="456pt" h="789pt"/>
  179. <medium stock="default" short="456pt" long="789pt"/>
  180. <draw name="BA-Logo" y="5.928mm" x="128.388mm" w="71.237mm" h="9.528mm">
  181. <value><text>foo</text></value>
  182. <assist role="H2"></assist>
  183. </draw>
  184. </pageArea>
  185. </pageSet>
  186. </subform>
  187. </template>
  188. <xfa:datasets xmlns:xfa="http://www.xfa.org/schema/xfa-data/1.0/">
  189. <xfa:data>
  190. </xfa:data>
  191. </xfa:datasets>
  192. </xdp:xdp>
  193. `;
  194. const factory = new XFAFactory({ "xdp:xdp": xml });
  195. expect(await factory.getNumPages()).toEqual(1);
  196. const pages = await factory.getPages();
  197. const page1 = pages.children[0];
  198. const wrapper = page1.children[0];
  199. const draw = wrapper.children[0];
  200. expect(draw.attributes.role).toEqual("heading");
  201. expect(draw.attributes["aria-level"]).toEqual("2");
  202. });
  203. it("should have aria table role", async () => {
  204. const xml = `
  205. <?xml version="1.0"?>
  206. <xdp:xdp xmlns:xdp="http://ns.adobe.com/xdp/">
  207. <template xmlns="http://www.xfa.org/schema/xfa-template/3.3">
  208. <subform name="root" mergeMode="matchTemplate">
  209. <pageSet>
  210. <pageArea>
  211. <contentArea x="0pt" w="456pt" h="789pt"/>
  212. <medium stock="default" short="456pt" long="789pt"/>
  213. <font size="7pt" typeface="FooBar" baselineShift="2pt">
  214. </font>
  215. </pageArea>
  216. </pageSet>
  217. <subform name="table" mergeMode="matchTemplate" layout="table">
  218. <subform layout="row" name="row1">
  219. <assist role="TH"></assist>
  220. <draw name="header1" y="5.928mm" x="128.388mm" w="71.237mm" h="9.528mm">
  221. <value><text>Header Col 1</text></value>
  222. </draw>
  223. <draw name="header2" y="5.928mm" x="128.388mm" w="71.237mm" h="9.528mm">
  224. <value><text>Header Col 2</text></value>
  225. </draw>
  226. </subform>
  227. <subform layout="row" name="row2">
  228. <draw name="cell1" y="5.928mm" x="128.388mm" w="71.237mm" h="9.528mm">
  229. <value><text>Cell 1</text></value>
  230. </draw>
  231. <draw name="cell2" y="5.928mm" x="128.388mm" w="71.237mm" h="9.528mm">
  232. <value><text>Cell 2</text></value>
  233. </draw>
  234. </subform>
  235. </subform>
  236. </subform>
  237. </template>
  238. <xfa:datasets xmlns:xfa="http://www.xfa.org/schema/xfa-data/1.0/">
  239. <xfa:data>
  240. </xfa:data>
  241. </xfa:datasets>
  242. </xdp:xdp>
  243. `;
  244. const factory = new XFAFactory({ "xdp:xdp": xml });
  245. factory.setFonts([]);
  246. expect(await factory.getNumPages()).toEqual(1);
  247. const pages = await factory.getPages();
  248. const table = searchHtmlNode(
  249. pages,
  250. "xfaName",
  251. "table",
  252. /* byAttributes */ true
  253. );
  254. expect(table.attributes.role).toEqual("table");
  255. const headerRow = searchHtmlNode(
  256. pages,
  257. "xfaName",
  258. "row1",
  259. /* byAttributes */ true
  260. );
  261. expect(headerRow.attributes.role).toEqual("row");
  262. const headerCell = searchHtmlNode(
  263. pages,
  264. "xfaName",
  265. "header2",
  266. /* byAttributes */ true
  267. );
  268. expect(headerCell.attributes.role).toEqual("columnheader");
  269. const row = searchHtmlNode(
  270. pages,
  271. "xfaName",
  272. "row2",
  273. /* byAttributes */ true
  274. );
  275. expect(row.attributes.role).toEqual("row");
  276. const cell = searchHtmlNode(
  277. pages,
  278. "xfaName",
  279. "cell2",
  280. /* byAttributes */ true
  281. );
  282. expect(cell.attributes.role).toEqual("cell");
  283. });
  284. it("should have a maxLength property", async () => {
  285. const xml = `
  286. <?xml version="1.0"?>
  287. <xdp:xdp xmlns:xdp="http://ns.adobe.com/xdp/">
  288. <template xmlns="http://www.xfa.org/schema/xfa-template/3.3">
  289. <subform name="root" mergeMode="matchTemplate">
  290. <pageSet>
  291. <pageArea>
  292. <contentArea x="0pt" w="456pt" h="789pt"/>
  293. <medium stock="default" short="456pt" long="789pt"/>
  294. <field y="1pt" w="11pt" h="22pt" x="2pt">
  295. <ui>
  296. <textEdit multiLine="0"/>
  297. </ui>
  298. <value>
  299. <text maxChars="123"/>
  300. </value>
  301. </field>
  302. </pageArea>
  303. </pageSet>
  304. <subform name="first">
  305. <draw w="1pt" h="1pt"><value><text>foo</text></value></draw>
  306. </subform>
  307. </subform>
  308. </template>
  309. <xfa:datasets xmlns:xfa="http://www.xfa.org/schema/xfa-data/1.0/">
  310. <xfa:data>
  311. </xfa:data>
  312. </xfa:datasets>
  313. </xdp:xdp>
  314. `;
  315. const factory = new XFAFactory({ "xdp:xdp": xml });
  316. expect(await factory.getNumPages()).toEqual(1);
  317. const pages = await factory.getPages();
  318. const field = searchHtmlNode(pages, "name", "input");
  319. expect(field.attributes.maxLength).toEqual(123);
  320. });
  321. it("should have an aria-label property from speak", async () => {
  322. const xml = `
  323. <?xml version="1.0"?>
  324. <xdp:xdp xmlns:xdp="http://ns.adobe.com/xdp/">
  325. <template xmlns="http://www.xfa.org/schema/xfa-template/3.3">
  326. <subform name="root" mergeMode="matchTemplate">
  327. <pageSet>
  328. <pageArea>
  329. <contentArea x="0pt" w="456pt" h="789pt"/>
  330. <medium stock="default" short="456pt" long="789pt"/>
  331. <field y="1pt" w="11pt" h="22pt" x="2pt">
  332. <assist><speak>Screen Reader</speak></assist>
  333. <ui>
  334. <textEdit multiLine="0"/>
  335. </ui>
  336. <value>
  337. <text maxChars="123"/>
  338. </value>
  339. </field>
  340. </pageArea>
  341. </pageSet>
  342. <subform name="first">
  343. <draw w="1pt" h="1pt"><value><text>foo</text></value></draw>
  344. </subform>
  345. </subform>
  346. </template>
  347. <xfa:datasets xmlns:xfa="http://www.xfa.org/schema/xfa-data/1.0/">
  348. <xfa:data>
  349. </xfa:data>
  350. </xfa:datasets>
  351. </xdp:xdp>
  352. `;
  353. const factory = new XFAFactory({ "xdp:xdp": xml });
  354. expect(await factory.getNumPages()).toEqual(1);
  355. const pages = await factory.getPages();
  356. const field = searchHtmlNode(pages, "name", "input");
  357. expect(field.attributes["aria-label"]).toEqual("Screen Reader");
  358. });
  359. it("should have an aria-label property from toolTip", async () => {
  360. const xml = `
  361. <?xml version="1.0"?>
  362. <xdp:xdp xmlns:xdp="http://ns.adobe.com/xdp/">
  363. <template xmlns="http://www.xfa.org/schema/xfa-template/3.3">
  364. <subform name="root" mergeMode="matchTemplate">
  365. <pageSet>
  366. <pageArea>
  367. <contentArea x="0pt" w="456pt" h="789pt"/>
  368. <medium stock="default" short="456pt" long="789pt"/>
  369. <field y="1pt" w="11pt" h="22pt" x="2pt">
  370. <assist><toolTip>Screen Reader</toolTip></assist>
  371. <ui>
  372. <textEdit multiLine="0"/>
  373. </ui>
  374. <value>
  375. <text maxChars="123"/>
  376. </value>
  377. </field>
  378. </pageArea>
  379. </pageSet>
  380. <subform name="first">
  381. <draw w="1pt" h="1pt"><value><text>foo</text></value></draw>
  382. </subform>
  383. </subform>
  384. </template>
  385. <xfa:datasets xmlns:xfa="http://www.xfa.org/schema/xfa-data/1.0/">
  386. <xfa:data>
  387. </xfa:data>
  388. </xfa:datasets>
  389. </xdp:xdp>
  390. `;
  391. const factory = new XFAFactory({ "xdp:xdp": xml });
  392. expect(await factory.getNumPages()).toEqual(1);
  393. const pages = await factory.getPages();
  394. const field = searchHtmlNode(pages, "name", "input");
  395. expect(field.attributes["aria-label"]).toEqual("Screen Reader");
  396. });
  397. it("should have an input or textarea", async () => {
  398. const xml = `
  399. <?xml version="1.0"?>
  400. <xdp:xdp xmlns:xdp="http://ns.adobe.com/xdp/">
  401. <template xmlns="http://www.xfa.org/schema/xfa-template/3.3">
  402. <subform name="root" mergeMode="matchTemplate">
  403. <pageSet>
  404. <pageArea>
  405. <contentArea x="123pt" w="456pt" h="789pt"/>
  406. <medium stock="default" short="456pt" long="789pt"/>
  407. <field y="1pt" w="11pt" h="22pt" x="2pt">
  408. <ui>
  409. <textEdit/>
  410. </ui>
  411. </field>
  412. <field y="1pt" w="11pt" h="22pt" x="2pt">
  413. <ui>
  414. <textEdit multiLine="1"/>
  415. </ui>
  416. </field>
  417. </pageArea>
  418. </pageSet>
  419. <subform name="first">
  420. <draw w="1pt" h="1pt"><value><text>foo</text></value></draw>
  421. </subform>
  422. </subform>
  423. </template>
  424. <xfa:datasets xmlns:xfa="http://www.xfa.org/schema/xfa-data/1.0/">
  425. <xfa:data>
  426. </xfa:data>
  427. </xfa:datasets>
  428. </xdp:xdp>
  429. `;
  430. const factory = new XFAFactory({ "xdp:xdp": xml });
  431. expect(await factory.getNumPages()).toEqual(1);
  432. const pages = await factory.getPages();
  433. const field1 = searchHtmlNode(pages, "name", "input");
  434. expect(field1).not.toEqual(null);
  435. const field2 = searchHtmlNode(pages, "name", "textarea");
  436. expect(field2).not.toEqual(null);
  437. });
  438. });
  439. it("should have an input or textarea", async () => {
  440. const xml = `
  441. <?xml version="1.0"?>
  442. <xdp:xdp xmlns:xdp="http://ns.adobe.com/xdp/">
  443. <template xmlns="http://www.xfa.org/schema/xfa-template/3.3">
  444. <subform name="root" mergeMode="matchTemplate">
  445. <pageSet>
  446. <pageArea>
  447. <contentArea x="123pt" w="456pt" h="789pt"/>
  448. <medium stock="default" short="456pt" long="789pt"/>
  449. <field y="1pt" w="11pt" h="22pt" x="2pt">
  450. <ui>
  451. <textEdit multiLine="1"/>
  452. </ui>
  453. </field>
  454. </pageArea>
  455. </pageSet>
  456. <subform name="first">
  457. <field y="1pt" w="11pt" h="22pt" x="2pt" name="hello">
  458. <ui>
  459. <textEdit/>
  460. </ui>
  461. <value>
  462. <integer/>
  463. </value>
  464. </field>
  465. </subform>
  466. </subform>
  467. </template>
  468. <xfa:datasets xmlns:xfa="http://www.xfa.org/schema/xfa-data/1.0/">
  469. <xfa:data>
  470. <toto>
  471. <first>
  472. <hello>123
  473. </hello>
  474. </first>
  475. </toto>
  476. </xfa:data>
  477. </xfa:datasets>
  478. </xdp:xdp>
  479. `;
  480. const factory = new XFAFactory({ "xdp:xdp": xml });
  481. expect(await factory.getNumPages()).toEqual(1);
  482. const pages = await factory.getPages();
  483. const field1 = searchHtmlNode(pages, "name", "input");
  484. expect(field1).not.toEqual(null);
  485. expect(field1.attributes.value).toEqual("123");
  486. });
  487. it("should parse URLs correctly", async () => {
  488. function getXml(href) {
  489. return `
  490. <?xml version="1.0"?>
  491. <xdp:xdp xmlns:xdp="http://ns.adobe.com/xdp/">
  492. <template xmlns="http://www.xfa.org/schema/xfa-template/3.3">
  493. <subform name="root" mergeMode="matchTemplate">
  494. <pageSet>
  495. <pageArea>
  496. <contentArea x="0pt" w="456pt" h="789pt"/>
  497. <medium stock="default" short="456pt" long="789pt"/>
  498. <draw name="url" y="5.928mm" x="128.388mm" w="71.237mm" h="9.528mm">
  499. <value>
  500. <exData contentType="text/html">
  501. <body xmlns="http://www.w3.org/1999/xhtml">
  502. <a href="${href}">${href}</a>
  503. </body>
  504. </exData>
  505. </value>
  506. </draw>
  507. </pageArea>
  508. </pageSet>
  509. </subform>
  510. </template>
  511. <xfa:datasets xmlns:xfa="http://www.xfa.org/schema/xfa-data/1.0/">
  512. <xfa:data>
  513. </xfa:data>
  514. </xfa:datasets>
  515. </xdp:xdp>
  516. `;
  517. }
  518. let factory, pages, a;
  519. // A valid, and complete, URL.
  520. factory = new XFAFactory({ "xdp:xdp": getXml("https://www.example.com/") });
  521. expect(await factory.getNumPages()).toEqual(1);
  522. pages = await factory.getPages();
  523. a = searchHtmlNode(pages, "name", "a");
  524. expect(a.value).toEqual("https://www.example.com/");
  525. expect(a.attributes.href).toEqual("https://www.example.com/");
  526. // A valid, but incomplete, URL.
  527. factory = new XFAFactory({ "xdp:xdp": getXml("www.example.com/") });
  528. expect(await factory.getNumPages()).toEqual(1);
  529. pages = await factory.getPages();
  530. a = searchHtmlNode(pages, "name", "a");
  531. expect(a.value).toEqual("www.example.com/");
  532. expect(a.attributes.href).toEqual("http://www.example.com/");
  533. // A valid email-address.
  534. factory = new XFAFactory({ "xdp:xdp": getXml("mailto:test@example.com") });
  535. expect(await factory.getNumPages()).toEqual(1);
  536. pages = await factory.getPages();
  537. a = searchHtmlNode(pages, "name", "a");
  538. expect(a.value).toEqual("mailto:test@example.com");
  539. expect(a.attributes.href).toEqual("mailto:test@example.com");
  540. // Not a valid URL.
  541. factory = new XFAFactory({ "xdp:xdp": getXml("qwerty/") });
  542. expect(await factory.getNumPages()).toEqual(1);
  543. pages = await factory.getPages();
  544. a = searchHtmlNode(pages, "name", "a");
  545. expect(a.value).toEqual("qwerty/");
  546. expect(a.attributes.href).toEqual("");
  547. });
  548. it("should replace button with an URL by a link", async () => {
  549. const xml = `
  550. <?xml version="1.0"?>
  551. <xdp:xdp xmlns:xdp="http://ns.adobe.com/xdp/">
  552. <template xmlns="http://www.xfa.org/schema/xfa-template/3.3">
  553. <subform name="root" mergeMode="matchTemplate">
  554. <pageSet>
  555. <pageArea>
  556. <contentArea x="123pt" w="456pt" h="789pt"/>
  557. <medium stock="default" short="456pt" long="789pt"/>
  558. </pageArea>
  559. </pageSet>
  560. <subform name="first">
  561. <field y="1pt" w="11pt" h="22pt" x="2pt">
  562. <ui>
  563. <button/>
  564. </ui>
  565. <event activity="click" name="event__click">
  566. <script contentType="application/x-javascript">
  567. app.launchURL("https://github.com/mozilla/pdf.js", true);
  568. </script>
  569. </event>
  570. </field>
  571. <field y="1pt" w="11pt" h="22pt" x="2pt">
  572. <ui>
  573. <button/>
  574. </ui>
  575. <event activity="click" name="event__click">
  576. <script contentType="application/x-javascript">
  577. xfa.host.gotoURL("https://github.com/allizom/pdf.js");
  578. </script>
  579. </event>
  580. </field>
  581. </subform>
  582. </subform>
  583. </template>
  584. <xfa:datasets xmlns:xfa="http://www.xfa.org/schema/xfa-data/1.0/">
  585. <xfa:data>
  586. </xfa:data>
  587. </xfa:datasets>
  588. </xdp:xdp>
  589. `;
  590. const factory = new XFAFactory({ "xdp:xdp": xml });
  591. expect(await factory.getNumPages()).toEqual(1);
  592. const pages = await factory.getPages();
  593. let a = searchHtmlNode(pages, "name", "a");
  594. expect(a.attributes.href).toEqual("https://github.com/mozilla/pdf.js");
  595. expect(a.attributes.newWindow).toEqual(true);
  596. a = searchHtmlNode(pages, "name", "a", false, [1]);
  597. expect(a.attributes.href).toEqual("https://github.com/allizom/pdf.js");
  598. expect(a.attributes.newWindow).toEqual(false);
  599. });
  600. });