Repository: apache/superset
File: superset-frontend/packages/superset-ui-core/src/components/AsyncAceEditor/AsyncAceEditor.test.tsx (TypeScript)

Code before:
    expect(firstPopup.dataset.aceAutocomplete).toBe('true');
  });

  // Remove the first popup from DOM (simulating ACE editor replacing it)
  firstPopup.remove();

  // Create a new autocomplete popup
  const secondPopup = document.createElement('div');
  secondPopup.className = 'ace_autocomplete';
  editorInstance.container?.appendChild(secondPopup);

  // Trigger command again - should find and move the new popup
  editorInstance.commands.exec('insertstring', editorInstance, ' ');

  await waitFor(() => {
    expect(secondPopup.dataset.aceAutocomplete).toBe('true');
    const parentContainer =
      editorInstance.container?.closest('#ace-editor') ??
      editorInstance.container?.parentElement;
    expect(parentContainer?.contains(secondPopup)).toBe(true);
  });
});

test('cleans up event listeners on unmount', async () => {
  const ref = createRef<AceEditor>();
  const { container, unmount } = render(<SQLEditor ref={ref as React.Ref<never>} />);

  await waitFor(() => {
    expect(container.querySelector(selector)).toBeInTheDocument();
  });

  const editorInstance = ref.current?.editor;
  expect(editorInstance).toBeDefined();

  if (!editorInstance) return;

  // Spy on the commands.off method
  const offSpy = jest.spyOn(editorInstance.commands, 'off');

  // Unmount the component
  unmount();

  // Verify that the event listener was removed
  expect(offSpy).toHaveBeenCalledWith('afterExec', expect.any(Function));

  offSpy.mockRestore();
});

test('does not move autocomplete popup if target container is document.body', async () => {
  const ref = createRef<AceEditor>();
  const { container } = render(<SQLEditor ref={ref as React.Ref<never>} />);

Review comment (suggestion):
```suggestion
  const { container, unmount } = render(
    <SQLEditor ref={ref as React.Ref<never>} />,
  );
```

Code after:
    expect(firstPopup.dataset.aceAutocomplete).toBe('true');
  });

  // Remove the first popup from DOM (simulating ACE editor replacing it)
  firstPopup.remove();

  // Create a new autocomplete popup
  const secondPopup = document.createElement('div');
  secondPopup.className = 'ace_autocomplete';
  editorInstance.container?.appendChild(secondPopup);

  // Trigger command again - should find and move the new popup
  editorInstance.commands.exec('insertstring', editorInstance, ' ');

  await waitFor(() => {
    expect(secondPopup.dataset.aceAutocomplete).toBe('true');
    const parentContainer =
      editorInstance.container?.closest('#ace-editor') ??
      editorInstance.container?.parentElement;
    expect(parentContainer?.contains(secondPopup)).toBe(true);
  });
});

test('cleans up event listeners on unmount', async () => {
  const ref = createRef<AceEditor>();
  const { container, unmount } = render(
    <SQLEditor ref={ref as React.Ref<never>} />,
  );
  await waitFor(() => {
    expect(container.querySelector(selector)).toBeInTheDocument();
  });

  const editorInstance = ref.current?.editor;
  expect(editorInstance).toBeDefined();

  if (!editorInstance) return;

  // Spy on the commands.off method
  const offSpy = jest.spyOn(editorInstance.commands, 'off');

  // Unmount the component
  unmount();

  // Verify that the event listener was removed
  expect(offSpy).toHaveBeenCalledWith('afterExec', expect.any(Function));

  offSpy.mockRestore();
});

test('does not move autocomplete popup if target container is document.body', async () => {
  const ref = createRef<AceEditor>();