@@ -12,7 +12,6 @@ import com.github.database.rider.core.api.dataset.ExpectedDataSet
1212import com.github.database.rider.junit5.api.DBRider
1313import org.assertj.core.api.Assertions.assertThat
1414import org.junit.jupiter.api.BeforeEach
15- import org.junit.jupiter.api.Disabled
1615import org.junit.jupiter.api.Test
1716import org.junit.jupiter.api.TestInstance
1817import org.skyscreamer.jsonassert.Customization
@@ -22,8 +21,10 @@ import org.skyscreamer.jsonassert.comparator.CustomComparator
2221import org.springframework.beans.factory.annotation.Autowired
2322import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc
2423import org.springframework.boot.test.context.SpringBootTest
24+ import org.springframework.http.HttpStatus
2525import org.springframework.http.MediaType
2626import org.springframework.test.web.servlet.MockMvc
27+ import org.springframework.test.web.servlet.delete
2728import org.springframework.test.web.servlet.get
2829import org.springframework.test.web.servlet.post
2930import org.springframework.util.MultiValueMapAdapter
@@ -1761,28 +1762,226 @@ class ArticleTest {
17611762 @TestInstance(TestInstance .Lifecycle .PER_CLASS )
17621763 @DBRider
17631764 class DeleteArticle {
1764- @Disabled
1765+
1766+ @Autowired
1767+ lateinit var mockMvc: MockMvc
1768+
1769+ @BeforeEach
1770+ fun reset () = DbConnection .resetSequence()
1771+
17651772 @Test
1773+ @DataSet(
1774+ value = [
1775+ " datasets/yml/given/users.yml" ,
1776+ " datasets/yml/given/tags.yml" ,
1777+ " datasets/yml/given/articles.yml" ,
1778+ ]
1779+ )
1780+ @ExpectedDataSet(
1781+ value = [" datasets/yml/then/api_integration/delete-success.yml" ],
1782+ ignoreCols = [" id" , " created_at" , " updated_at" ],
1783+ orderBy = [" id" ]
1784+ )
1785+ // NOTE: @ExportDataSetはgivenの@DataSetが変更された時用に残しておく
1786+ // @ExportDataSet(
1787+ // format = DataSetFormat.YML,
1788+ // outputName = "src/test/resources/datasets/yml/then/api_integration/delete-success.yml",
1789+ // includeTables = ["articles", "tags", "article_tags", "favorites", "article_comments"]
1790+ // )
17661791 fun `正常系-自分が著者である記事のSlugを指定した場合、その作成済み記事を削除する` () {
1767- TODO ()
1792+ /* *
1793+ * given:
1794+ * - 存在する著者
1795+ * - 著者が書いた作成済み記事のslug
1796+ */
1797+ val author = SeedData .users().first()
1798+ val sessionToken = MySessionJwtImpl .encode(MySession (author.userId, author.email))
1799+ .getOrHandle { throw UnsupportedOperationException (" セッションからJWTへの変換に失敗しました(前提条件であるため、元の実装を見直してください)" ) }
1800+ val slug = " rust-vs-scala-vs-kotlin"
1801+
1802+ /* *
1803+ * when:
1804+ */
1805+ val response = mockMvc.delete(" /articles/$slug " ) {
1806+ contentType = MediaType .APPLICATION_JSON
1807+ header(" Authorization" , sessionToken)
1808+ }.andReturn().response
1809+ val actualStatus = response.status
1810+ val actualResponseBody = response.contentAsString
1811+
1812+ /* *
1813+ * then:
1814+ */
1815+ val expectedStatus = HttpStatus .OK .value()
1816+ val expectedResponseBody = " "
1817+ assertThat(actualStatus).isEqualTo(expectedStatus)
1818+ assertThat(actualResponseBody).isEqualTo(expectedResponseBody)
17681819 }
17691820
1770- @Disabled
17711821 @Test
1822+ @DataSet(
1823+ value = [
1824+ " datasets/yml/given/users.yml" ,
1825+ " datasets/yml/given/tags.yml" ,
1826+ " datasets/yml/given/articles.yml" ,
1827+ ]
1828+ )
1829+ @ExpectedDataSet(
1830+ value = [
1831+ " datasets/yml/given/tags.yml" ,
1832+ " datasets/yml/given/articles.yml" ,
1833+ ],
1834+ ignoreCols = [" id" , " created_at" , " updated_at" ],
1835+ orderBy = [" id" ]
1836+ )
17721837 fun `準正常系-自分が著者ではない記事のSlugを指定した場合、その作成済み記事は削除できない` () {
1773- TODO ()
1838+ /* *
1839+ * given:
1840+ * - 著者ではない存在する登録済みユーザー
1841+ * - 登録済み記事のslug
1842+ */
1843+ val author = SeedData .users().toList()[1 ]
1844+ val sessionToken = MySessionJwtImpl .encode(MySession (author.userId, author.email))
1845+ .getOrHandle { throw UnsupportedOperationException (" セッションからJWTへの変換に失敗しました(前提条件であるため、元の実装を見直してください)" ) }
1846+ val slug = " rust-vs-scala-vs-kotlin"
1847+
1848+ /* *
1849+ * when:
1850+ */
1851+ val response = mockMvc.delete(" /articles/$slug " ) {
1852+ contentType = MediaType .APPLICATION_JSON
1853+ header(" Authorization" , sessionToken)
1854+ }.andReturn().response
1855+ val actualStatus = response.status
1856+ val actualResponseBody = response.contentAsString
1857+
1858+ /* *
1859+ * then:
1860+ */
1861+ val expectedStatus = HttpStatus .UNPROCESSABLE_ENTITY .value()
1862+ val expectedResponseBody = """
1863+ {"errors":{"body":["削除する権限がありません"]}}
1864+ """ .trimIndent()
1865+ assertThat(actualStatus).isEqualTo(expectedStatus)
1866+ JSONAssert .assertEquals(
1867+ expectedResponseBody,
1868+ actualResponseBody,
1869+ CustomComparator (JSONCompareMode .NON_EXTENSIBLE )
1870+ )
17741871 }
17751872
1776- @Disabled
17771873 @Test
1874+ @DataSet(
1875+ value = [
1876+ " datasets/yml/given/users.yml" ,
1877+ " datasets/yml/given/tags.yml" ,
1878+ " datasets/yml/given/articles.yml" ,
1879+ ]
1880+ )
1881+ @ExpectedDataSet(
1882+ value = [
1883+ " datasets/yml/given/tags.yml" ,
1884+ " datasets/yml/given/articles.yml" ,
1885+ ],
1886+ ignoreCols = [" id" , " created_at" , " updated_at" ],
1887+ orderBy = [" id" ]
1888+ )
17781889 fun `準正常系-存在しないSlugを指定した場合、その作成済み記事は見つからなかった旨のエラーレスポンスが返る` () {
1779- TODO ()
1890+ /* *
1891+ * given:
1892+ * - 存在する登録済みユーザー
1893+ * - 存在しないslug
1894+ */
1895+ val existedUser = SeedData .users().first()
1896+ val sessionToken = MySessionJwtImpl .encode(MySession (existedUser.userId, existedUser.email))
1897+ .getOrHandle { throw UnsupportedOperationException (" セッションからJWTへの変換に失敗しました(前提条件であるため、元の実装を見直してください)" ) }
1898+ val slug = " not-existed-slug"
1899+
1900+ /* *
1901+ * when:
1902+ */
1903+ val response = mockMvc.delete(" /articles/$slug " ) {
1904+ contentType = MediaType .APPLICATION_JSON
1905+ header(" Authorization" , sessionToken)
1906+ }.andReturn().response
1907+ val actualStatus = response.status
1908+ val actualResponseBody = response.contentAsString
1909+
1910+ /* *
1911+ * then:
1912+ */
1913+ val expectedStatus = HttpStatus .UNPROCESSABLE_ENTITY .value()
1914+ val expectedResponseBody = """
1915+ {"errors":{"body":["記事が見つかりませんでした"]}}
1916+ """ .trimIndent()
1917+ assertThat(actualStatus).isEqualTo(expectedStatus)
1918+ JSONAssert .assertEquals(
1919+ expectedResponseBody,
1920+ actualResponseBody,
1921+ CustomComparator (JSONCompareMode .NON_EXTENSIBLE )
1922+ )
17801923 }
17811924
1782- @Disabled
17831925 @Test
1784- fun `準正常系-バリデーションエラーが起こるSlugを指定した場合、その作成済み記事は見つからなかった旨のエラーレスポンスが返る` () {
1785- TODO ()
1926+ @DataSet(
1927+ value = [
1928+ " datasets/yml/given/users.yml" ,
1929+ " datasets/yml/given/tags.yml" ,
1930+ " datasets/yml/given/articles.yml" ,
1931+ ]
1932+ )
1933+ @ExpectedDataSet(
1934+ value = [
1935+ " datasets/yml/given/tags.yml" ,
1936+ " datasets/yml/given/articles.yml" ,
1937+ ],
1938+ ignoreCols = [" id" , " created_at" , " updated_at" ],
1939+ orderBy = [" id" ]
1940+ )
1941+ fun `準正常系-バリデーションエラーが起こるSlugを指定した場合、その旨のエラーレスポンスが返る` () {
1942+ /* *
1943+ * given:
1944+ * - 存在する登録済みユーザー
1945+ * - バリデーションエラーが起こるslug
1946+ */
1947+ val existedUser = SeedData .users().first()
1948+ val sessionToken = MySessionJwtImpl .encode(MySession (existedUser.userId, existedUser.email))
1949+ .getOrHandle { throw UnsupportedOperationException (" セッションからJWTへの変換に失敗しました(前提条件であるため、元の実装を見直してください)" ) }
1950+ val slug = IntStream .range(0 , 10 ).mapToObj { " 長すぎるslug" }.toList().joinToString()
1951+
1952+ /* *
1953+ * when:
1954+ */
1955+ val response = mockMvc.delete(" /articles/$slug " ) {
1956+ contentType = MediaType .APPLICATION_JSON
1957+ header(" Authorization" , sessionToken)
1958+ }.andReturn().response
1959+ val actualStatus = response.status
1960+ val actualResponseBody = response.contentAsString
1961+
1962+ /* *
1963+ * then:
1964+ */
1965+ val expectedStatus = HttpStatus .UNPROCESSABLE_ENTITY .value()
1966+ val expectedResponseBody = """
1967+ {
1968+ "errors":{
1969+ "body":[
1970+ {
1971+ "slug": "長すぎるslug, 長すぎるslug, 長すぎるslug, 長すぎるslug, 長すぎるslug, 長すぎるslug, 長すぎるslug, 長すぎるslug, 長すぎるslug, 長すぎるslug",
1972+ "key":"Slug",
1973+ "message":"slugは32文字以下にしてください。"
1974+ }
1975+ ]
1976+ }
1977+ }
1978+ """ .trimIndent()
1979+ assertThat(actualStatus).isEqualTo(expectedStatus)
1980+ JSONAssert .assertEquals(
1981+ expectedResponseBody,
1982+ actualResponseBody,
1983+ CustomComparator (JSONCompareMode .NON_EXTENSIBLE )
1984+ )
17861985 }
17871986 }
17881987}
0 commit comments