void () { @NonNls @Language("XML") final String text = """ <preface> <para> TODO </para> </preface> """; final PsiFile file = myFixture.addFileToProject("aaa.xml", text); PsiDocumentManager.getInstance(getProject()).commitAllDocuments(); final List<PsiElement> added = new ArrayList<>(); final List<PsiElement> removed = new ArrayList<>(); final List<PsiElement> replaced = new ArrayList<>(); final List<PsiElement> moved = new ArrayList<>(); file.getManager().addPsiTreeChangeListener(new PsiTreeChangeAdapter(){ @Override public void childAdded(@NotNull PsiTreeChangeEvent event) { added.add(event.getChild()); } @Override public void childRemoved(@NotNull PsiTreeChangeEvent event) { removed.add(event.getElement()); } @Override public void childReplaced(@NotNull PsiTreeChangeEvent event) { replaced.add(event.getOldChild()); } @Override public void childMoved(@NotNull PsiTreeChangeEvent event) { moved.add(event.getElement()); } }, getTestRootDisposable()); WriteCommandAction.runWriteCommandAction(getProject(), () -> { Document document = PsiDocumentManager.getInstance(getProject()).getDocument(file); int offset = document.getText().indexOf("</para>\n\n") + "</para>\n\n".length(); document.insertString(offset, "<another></another>"); PsiDocumentManager.getInstance(getProject()).commitAllDocuments(); }); assertEquals(2, added.size()); assertTrue(added.get(0) instanceof XmlTag); assertEquals("<another></another>", added.get(0).getText()); assertTrue(added.get(1) instanceof XmlText); assertEquals("\n", added.get(1).getText()); assertEmpty(removed); assertEmpty(moved); assertEmpty(replaced); }