handleTestCondition.js 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. import { nanoid } from 'nanoid';
  2. import { visibleInViewport } from '@/utils/helper';
  3. import FindElement from '@/utils/FindElement';
  4. import { automaRefDataStr } from './utils';
  5. function handleConditionElement({ data, type }) {
  6. const selectorType = data.selector.startsWith('/') ? 'xpath' : 'cssSelector';
  7. const element = FindElement[selectorType](data);
  8. const { 1: actionType } = type.split('#');
  9. const elementActions = {
  10. exists: () => Boolean(element),
  11. notExists: () => !element,
  12. text: () => element?.innerText ?? null,
  13. visibleScreen: () => {
  14. if (!element) return false;
  15. return visibleInViewport(element);
  16. },
  17. visible: () => {
  18. if (!element) return false;
  19. const { visibility, display } = getComputedStyle(element);
  20. return visibility !== 'hidden' && display !== 'none';
  21. },
  22. invisible: () => {
  23. if (!element) return false;
  24. const { visibility, display } = getComputedStyle(element);
  25. const styleHidden = visibility === 'hidden' || display === 'none';
  26. return styleHidden || !visibleInViewport(element);
  27. },
  28. attribute: ({ attrName }) => {
  29. if (!element || !element.hasAttribute(attrName)) return null;
  30. return element.getAttribute(attrName);
  31. },
  32. };
  33. return elementActions[actionType](data);
  34. }
  35. function injectJsCode({ data, refData }) {
  36. return new Promise((resolve, reject) => {
  37. const stateId = nanoid();
  38. sessionStorage.setItem(`automa--${stateId}`, JSON.stringify(refData));
  39. const scriptEl = document.createElement('script');
  40. scriptEl.textContent = `
  41. (async () => {
  42. ${automaRefDataStr(stateId)}
  43. try {
  44. ${data.code}
  45. } catch (error) {
  46. return {
  47. $isError: true,
  48. message: error.message,
  49. }
  50. }
  51. })()
  52. .then((detail) => {
  53. window.dispatchEvent(new CustomEvent('__automa-condition-code__', { detail }));
  54. });
  55. `;
  56. document.body.appendChild(scriptEl);
  57. const handleAutomaEvent = ({ detail }) => {
  58. scriptEl.remove();
  59. window.removeEventListener(
  60. '__automa-condition-code__',
  61. handleAutomaEvent
  62. );
  63. if (detail.$isError) {
  64. reject(new Error(detail.message));
  65. return;
  66. }
  67. resolve(detail);
  68. };
  69. window.addEventListener('__automa-condition-code__', handleAutomaEvent);
  70. });
  71. }
  72. export default async function (data) {
  73. let result = null;
  74. if (data.type.startsWith('element')) {
  75. result = await handleConditionElement(data);
  76. }
  77. if (data.type.startsWith('code')) {
  78. result = await injectJsCode(data);
  79. }
  80. return result;
  81. }