Extract and set form values through the DOM—no frameworks required! https://github.com/TheoryOfNekomata/formxtra
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

133 lines
3.3 KiB

  1. /// <reference types="cypress" />
  2. import JSDOMDummyCypress from './jsdom-compat'
  3. type ExpectedSearchValue = any
  4. type RetrieveSubmitterFn = (wrapper: typeof cy | JSDOMDummyCypress) => any
  5. type HTMLSubmitterElement = HTMLButtonElement | HTMLInputElement
  6. type TestFn = (form: HTMLFormElement, submitter: HTMLSubmitterElement, after: ExpectedSearchValue) => unknown
  7. export const setup = (template: string) => {
  8. if (typeof cy !== 'undefined') {
  9. return () => {
  10. cy.intercept({ url: '/' }, { body: template });
  11. cy.intercept({ url: '/?*' }, { body: template }).as('submitted');
  12. }
  13. }
  14. return () => {
  15. // @ts-ignore
  16. window.document.open(undefined, undefined, undefined, true)
  17. window.document.write(template)
  18. window.document.close()
  19. }
  20. }
  21. type TestOptions = {
  22. action: RetrieveSubmitterFn,
  23. test: TestFn,
  24. expectedStaticValue?: ExpectedSearchValue,
  25. preAction?: Function,
  26. }
  27. export const test = (options: TestOptions) => {
  28. const {
  29. action: retrieveSubmitterFn,
  30. test: testFn,
  31. expectedStaticValue,
  32. preAction,
  33. } = options;
  34. let form: HTMLFormElement
  35. let submitter: HTMLButtonElement | HTMLInputElement
  36. let r: any
  37. if (typeof cy !== 'undefined') {
  38. cy
  39. .visit('/')
  40. .get('form')
  41. .then((formResult: any) => {
  42. [form] = Array.from(formResult);
  43. if (typeof preAction === 'function') {
  44. preAction(form);
  45. }
  46. })
  47. r = retrieveSubmitterFn(cy)
  48. .then((submitterQueryEl: any) => {
  49. [submitter] = Array.from(submitterQueryEl as any[])
  50. })
  51. if (typeof expectedStaticValue !== 'undefined') {
  52. r.click()
  53. cy
  54. .wait('@submitted')
  55. .location('search')
  56. .then((search: any) => {
  57. testFn(form, submitter, search)
  58. })
  59. } else {
  60. cy
  61. .location('search')
  62. .then((search: any) => {
  63. testFn(form, submitter, search)
  64. })
  65. }
  66. } else {
  67. r = retrieveSubmitterFn(new JSDOMDummyCypress())
  68. .then((submitterQueryEl: any) => {
  69. [submitter] = Array.from(submitterQueryEl as any[]);
  70. [form] = Array.from(window.document.getElementsByTagName('form'))
  71. if (typeof preAction === 'function') {
  72. preAction(form);
  73. }
  74. testFn(form, submitter, expectedStaticValue)
  75. })
  76. if (typeof expectedStaticValue !== 'undefined') {
  77. r.click()
  78. }
  79. }
  80. }
  81. export const makeSearchParams = (beforeValues: Record<string, unknown> | string) => {
  82. switch (typeof (beforeValues as unknown)) {
  83. case 'string':
  84. return new URLSearchParams(beforeValues as string)
  85. case 'object':
  86. return Object
  87. .entries(beforeValues)
  88. .filter(([k]) => k.trim().length > 0)
  89. .reduce(
  90. (beforeSearchParams, [key, value]) => {
  91. const theValue = !Array.isArray(value) ? [value] : value
  92. theValue.forEach(v => {
  93. let processedLineBreaks = v
  94. if (typeof cy !== 'undefined') {
  95. let forceLineBreaks: string;
  96. // TODO make this foolproof
  97. if (navigator.platform.indexOf("Mac") === 0 ||
  98. navigator.platform === "iPhone") {
  99. forceLineBreaks = '\n';
  100. } else if (navigator.platform === 'Win32') {
  101. forceLineBreaks = '\r\n';
  102. }
  103. processedLineBreaks = processedLineBreaks
  104. .replace(/(\r\n|\r|\n)/g, forceLineBreaks)
  105. }
  106. beforeSearchParams.append(key, processedLineBreaks)
  107. })
  108. return beforeSearchParams
  109. },
  110. new URLSearchParams()
  111. )
  112. default:
  113. break
  114. }
  115. throw new TypeError('Invalid parameter.')
  116. }