diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/refactoring/introduce/InplaceExtractFunctionTest.kt b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/refactoring/introduce/InplaceExtractFunctionTest.kt
new file mode 100644
index 000000000000..219c3ea35874
--- /dev/null
+++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/refactoring/introduce/InplaceExtractFunctionTest.kt
@@ -0,0 +1,68 @@
+// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
+package org.jetbrains.kotlin.idea.refactoring.introduce
+
+import com.intellij.codeInsight.template.impl.TemplateManagerImpl
+import com.intellij.codeInsight.template.impl.TemplateState
+import com.intellij.openapi.command.WriteCommandAction
+import com.intellij.testFramework.TestDataPath
+import com.intellij.util.ui.UIUtil
+import junit.framework.TestCase
+import org.jetbrains.kotlin.idea.refactoring.introduce.extractFunction.ExtractKotlinFunctionHandler
+import org.jetbrains.kotlin.idea.test.JUnit3RunnerWithInners
+import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
+import org.jetbrains.kotlin.idea.test.TestRoot
+import org.jetbrains.kotlin.test.TestMetadata
+import org.junit.runner.RunWith
+
+@TestRoot("idea/tests")
+@TestDataPath("\$CONTENT_ROOT")
+@TestMetadata("testData/refactoring/extractFunction/inplace")
+@RunWith(JUnit3RunnerWithInners::class)
+class InplaceExtractFunctionTest : KotlinLightCodeInsightFixtureTestCase() {
+
+ fun testStringTemplate() {
+ doTest()
+ }
+
+ fun testStringTemplateWithNameConflict() {
+ doTest(changedName = "substring")
+ }
+
+ fun testConflictNameNotAccepted() {
+ doTest(changedName = "conflict", checkResult = false)
+ TestCase.assertTrue(getActiveTemplate() != null)
+ }
+
+ fun testConsecutiveDuplicates() {
+ doTest(changedName = "renamed")
+ }
+
+ fun testExposedAssignment() {
+ doTest(changedName = "getX")
+ }
+
+ fun doTest(changedName: String? = null, checkResult: Boolean = true) {
+ TemplateManagerImpl.setTemplateTesting(testRootDisposable)
+ myFixture.configureByFile("${getTestName(false)}.kt")
+ ExtractKotlinFunctionHandler().invoke(myFixture.project, myFixture.editor, myFixture.file, null)
+ val template = getActiveTemplate()
+ require(template != null) { "Failed to start refactoring" }
+ if (changedName != null) {
+ renameTemplate(template, changedName)
+ }
+ template.gotoEnd(false)
+ UIUtil.dispatchAllInvocationEvents()
+ if (checkResult) {
+ myFixture.checkResultByFile("${getTestName(false)}.after.kt")
+ }
+ }
+
+ private fun getActiveTemplate() = TemplateManagerImpl.getTemplateState(editor)
+
+ private fun renameTemplate(templateState: TemplateState, name: String) {
+ WriteCommandAction.runWriteCommandAction(project) {
+ val range = templateState.currentVariableRange!!
+ editor.document.replaceString(range.startOffset, range.endOffset, name)
+ }
+ }
+}
\ No newline at end of file
diff --git a/plugins/kotlin/idea/tests/testData/refactoring/extractFunction/inplace/ConflictNameNotAccepted.after.kt b/plugins/kotlin/idea/tests/testData/refactoring/extractFunction/inplace/ConflictNameNotAccepted.after.kt
new file mode 100644
index 000000000000..92bb0a6ba417
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/refactoring/extractFunction/inplace/ConflictNameNotAccepted.after.kt
@@ -0,0 +1,3 @@
+fun sample(){
+ println("42")
+}
\ No newline at end of file
diff --git a/plugins/kotlin/idea/tests/testData/refactoring/extractFunction/inplace/ConflictNameNotAccepted.kt b/plugins/kotlin/idea/tests/testData/refactoring/extractFunction/inplace/ConflictNameNotAccepted.kt
new file mode 100644
index 000000000000..e7963fed3faf
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/refactoring/extractFunction/inplace/ConflictNameNotAccepted.kt
@@ -0,0 +1,6 @@
+fun sample(){
+ println("42")
+}
+
+fun conflict(){
+}
\ No newline at end of file
diff --git a/plugins/kotlin/idea/tests/testData/refactoring/extractFunction/inplace/ConsecutiveDuplicates.after.kt b/plugins/kotlin/idea/tests/testData/refactoring/extractFunction/inplace/ConsecutiveDuplicates.after.kt
new file mode 100644
index 000000000000..72023161e271
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/refactoring/extractFunction/inplace/ConsecutiveDuplicates.after.kt
@@ -0,0 +1,8 @@
+fun sample(){
+ renamed()
+ renamed()
+}
+
+private fun renamed() {
+ println("duplicate")
+}
\ No newline at end of file
diff --git a/plugins/kotlin/idea/tests/testData/refactoring/extractFunction/inplace/ConsecutiveDuplicates.kt b/plugins/kotlin/idea/tests/testData/refactoring/extractFunction/inplace/ConsecutiveDuplicates.kt
new file mode 100644
index 000000000000..8a579f13d0a8
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/refactoring/extractFunction/inplace/ConsecutiveDuplicates.kt
@@ -0,0 +1,4 @@
+fun sample(){
+ println("duplicate")
+ println("duplicate")
+}
\ No newline at end of file
diff --git a/plugins/kotlin/idea/tests/testData/refactoring/extractFunction/inplace/ExposedAssignment.after.kt b/plugins/kotlin/idea/tests/testData/refactoring/extractFunction/inplace/ExposedAssignment.after.kt
new file mode 100644
index 000000000000..7df567326498
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/refactoring/extractFunction/inplace/ExposedAssignment.after.kt
@@ -0,0 +1,11 @@
+fun sample(){
+ val x = getX()
+
+ println(x)
+}
+
+private fun getX(): Int {
+ val x = 42
+ println()
+ return x
+}
\ No newline at end of file
diff --git a/plugins/kotlin/idea/tests/testData/refactoring/extractFunction/inplace/ExposedAssignment.kt b/plugins/kotlin/idea/tests/testData/refactoring/extractFunction/inplace/ExposedAssignment.kt
new file mode 100644
index 000000000000..bfcb9cfec33b
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/refactoring/extractFunction/inplace/ExposedAssignment.kt
@@ -0,0 +1,6 @@
+fun sample(){
+ val x = 42
+ println()
+
+ println(x)
+}
\ No newline at end of file
diff --git a/plugins/kotlin/idea/tests/testData/refactoring/extractFunction/inplace/StringTemplate.after.kt b/plugins/kotlin/idea/tests/testData/refactoring/extractFunction/inplace/StringTemplate.after.kt
new file mode 100644
index 000000000000..906e8702b3a1
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/refactoring/extractFunction/inplace/StringTemplate.after.kt
@@ -0,0 +1,3 @@
+val example = "STRING_${extracted()}_BIG"
+
+private fun extracted() = "SAMPLE"
\ No newline at end of file
diff --git a/plugins/kotlin/idea/tests/testData/refactoring/extractFunction/inplace/StringTemplate.kt b/plugins/kotlin/idea/tests/testData/refactoring/extractFunction/inplace/StringTemplate.kt
new file mode 100644
index 000000000000..6c388b5c83fd
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/refactoring/extractFunction/inplace/StringTemplate.kt
@@ -0,0 +1 @@
+val example = "STRING_SAMPLE_BIG"
\ No newline at end of file
diff --git a/plugins/kotlin/idea/tests/testData/refactoring/extractFunction/inplace/StringTemplateWithNameConflict.after.kt b/plugins/kotlin/idea/tests/testData/refactoring/extractFunction/inplace/StringTemplateWithNameConflict.after.kt
new file mode 100644
index 000000000000..0f699e2562dd
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/refactoring/extractFunction/inplace/StringTemplateWithNameConflict.after.kt
@@ -0,0 +1,5 @@
+val example = "STRING_${substring()}_BIG"
+
+private fun substring() = "SAMPLE"
+
+fun extracted(): String = "42"
\ No newline at end of file
diff --git a/plugins/kotlin/idea/tests/testData/refactoring/extractFunction/inplace/StringTemplateWithNameConflict.kt b/plugins/kotlin/idea/tests/testData/refactoring/extractFunction/inplace/StringTemplateWithNameConflict.kt
new file mode 100644
index 000000000000..596558e9ec3f
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/refactoring/extractFunction/inplace/StringTemplateWithNameConflict.kt
@@ -0,0 +1,3 @@
+val example = "STRING_SAMPLE_BIG"
+
+fun extracted(): String = "42"
\ No newline at end of file