Created
April 24, 2015 03:19
-
-
Save bigwheel/26d0fbda3688672ebd58 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package utils.specs2 | |
| import org.specs2.main.SmartDiffs | |
| import play.api.libs.json._ | |
| import scala.util.Success | |
| import scala.util.Try | |
| object JsonProcessableDiffs extends SmartDiffs { | |
| private[this] def toJsObectOption(map: Map[String, JsValue]) = if (map.isEmpty) | |
| None | |
| else | |
| Some(JsObject(map.toSeq)) | |
| private[this] def toJsArrayOption(seq: Seq[Option[JsValue]]) = if (seq.forall(_ == None)) | |
| None | |
| else | |
| //Some(JsArray(seq.map(_.orNull))) | |
| Some(JsArray(seq.map(_.getOrElse(JsNull)))) | |
| private[this] def chooseOnlyDifferenceElements: (JsValue, JsValue) => Option[(Option[JsValue], Option[JsValue])] = { | |
| case (jsValueA, jsValueB) if jsValueA == jsValueB => | |
| None: Option[(Option[JsValue], Option[JsValue])] | |
| // なぜかIntellijの推論がうまく働かずエラー表示されるので型情報を明示する | |
| case (jsObjectA: JsObject, jsObjectB: JsObject) => | |
| val unionedKeys = jsObjectA.keys ++ jsObjectB.keys | |
| val differenceElementsMap = unionedKeys.map { key => | |
| key -> chooseOnlyDifferenceElements(jsObjectA \ key, jsObjectB \ key) | |
| }.toMap | |
| val mapA = differenceElementsMap.map { | |
| case (key, Some(Tuple2(Some(jsValue), _))) if !jsValue.isInstanceOf[JsUndefined] => | |
| Some(key -> jsValue) | |
| case _ => None | |
| }.flatten.toMap | |
| val mapB = differenceElementsMap.map { | |
| case (key, Some(Tuple2(_, Some(jsValue)))) if !jsValue.isInstanceOf[JsUndefined] => | |
| Some(key -> jsValue) | |
| case _ => None | |
| }.flatten.toMap | |
| Some((toJsObectOption(mapA), toJsObectOption(mapB))) | |
| case (jsArrayA: JsArray, jsArrayB: JsArray) => | |
| val maxSize = Seq(jsArrayA.value.size, jsArrayB.value.size).max | |
| val differenceElements = Range(0, maxSize).map { index => | |
| chooseOnlyDifferenceElements(jsArrayA(index), jsArrayB(index)) | |
| } | |
| val seqA = differenceElements.map { | |
| /** @todo JsObjectと同様にJsUndefined時の処理を追加する */ | |
| case Some(Tuple2(Some(jsValue), _)) => Some(jsValue) | |
| case _ => None | |
| } | |
| val seqB = differenceElements.map { | |
| /** @todo JsObjectと同様にJsUndefined時の処理を追加する */ | |
| case Some(Tuple2(_, Some(jsValue))) => Some(jsValue) | |
| case _ => None | |
| } | |
| Some((toJsArrayOption(seqA), toJsArrayOption(seqB))) | |
| case (jsValueA, jsValueB) => Some((Some(jsValueA), Some(jsValueB))) | |
| } | |
| override def showDiffs(expected: String, actual: String): (String, String) = | |
| (Try(Json.parse(expected)), Try(Json.parse(actual))) match { | |
| case (Success(expectedJson), Success(actualJson)) => | |
| val (trimedExpected, trimedActual) = chooseOnlyDifferenceElements(expectedJson, actualJson). | |
| getOrElse(throw new IllegalStateException( | |
| "違いがあってこのメソッドが呼ばれてるのにtrimした結果が空 = 違いがない。おかしい")) | |
| ( | |
| trimedExpected.map(Json.prettyPrint).getOrElse(""), | |
| trimedActual.map(Json.prettyPrint).getOrElse("") | |
| ) | |
| case _ => super.showDiffs(expected, actual) | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment