All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.scalatest.StreamlinedXml.scala Maven / Gradle / Ivy

/*
 * Copyright 2001-2014 Artima, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.scalatest

import scala.xml.{Text, Node, Elem, NodeSeq}
import org.scalactic.Uniformity

/**
 * Trait providing a streamlined method that returns a Uniformity[T]
 * instance for any subtype of scala.xml.NodeSeq that will normalize the XML by removing empty text nodes and trimming
 * non-empty text nodes.
 *
 * 

* Here's an example of some unnormalized XML: *

* *
 * <summer>
 *   <day></day>
 *   <night>
 *     with lots of stars
 *   </night>
 * </summer>
 * 
* *

* The Uniformity returned by this trait's streamlined method would transform * the above XML to: *

* *
 * <summer><day></day><night>with lots of stars</night></summer>
 * 
* *

* The streamlined method can be used with the Explicitly DSL, like this: *

* *
 * xmlElem should equal (
 *   <summer>
 *     <day></day>
 *     <night>
 *       with lots of stars
 *     </night>
 *   </summer>
 * ) (after being streamlined[Elem])
 * 
* *

* The goal of this trait is to provide a normalization for XML that makes it easier to test XML objects for equality. * White space is significant in XML, and is taken into account by the default equality for XML, accessed * by invoking the == method on an XML NodeSeq. Here's an example: *

* *
 * scala> val xmlElem = <summer><day></day><night>with lots of stars</night></summer>
 * xmlElem: scala.xml.Elem = <summer><day></day><night>with lots of stars</night></summer>
 *
 * scala> xmlElem == <summer>
 *      |   <day></day>
 *      |   <night>
 *      |     with lots of stars
 *      |   </night>
 *      | </summer>
 * res1: Boolean = false
 * 
* *

* The above equality comparison produces false because of whitespace differences in the XML. * When such whitespace differences are unimportant to the actual application, it can make it * easier to write readable test code if you can compare XML for equality without taking * into account empty text nodes, or leading and trailing whitespace in nonempty text nodes. * The streamlined method of this trait provides a Uniformity * instance that does just that: *

* *
 * scala> import org.scalactic._
 * import org.scalactic._
 *
 * scala> import Explicitly._
 * import Explicitly._
 *
 * scala> import TripleEquals._
 * import TripleEquals._
 *
 * scala> import org.scalatest.StreamlinedXml._
 * import StreamlinedXml._
 *
 * scala> import scala.xml.Elem
 * import scala.xml.Elem * 
 * 
 * scala> (xmlElem === <summer>
 *      |   <day></day>
 *      |   <night>
 *      |     with lots of stars
 *      |   </night>
 *      | </summer>) (after being streamlined[Elem])
 * res9: Boolean = true
 * 
* * @author Bill Venners */ trait StreamlinedXml { /** * Provides a Uniformity[T] * instance for any subtype of scala.xml.NodeSeq that will normalize the XML by removing empty text nodes and trimming * non-empty text nodes. * *

* The purpose of this Uniformity is to make it easier to write readable test * code that compares XML for equality. See the main documentation for this trait for more * details and examples. *

* * @return a Uniformity[T] instance that normalizes XML for testing */ def streamlined[T <: NodeSeq]: Uniformity[T] = { def trimTextZappingEmpty(node: Node): Seq[Node] = node match { case Text(text) if (text.trim.isEmpty) => Nil case Text(text) => List(Text(text.trim)) case Elem(pre, lab, md, scp, children @ _*) => Elem(pre, lab, md, scp, false, (children.flatMap(trimTextZappingEmpty)):_*) case _ => List(node) } new Uniformity[T] { def normalized(nodeSeq: T): T = nodeSeq match { case Elem(pre, lab, md, scp, children @ _*) => val mergedTextNodes = // Merge adjacent text nodes children.foldLeft(Nil: List[Node]) { (acc, ele) => ele match { case eleTxt: Text => acc.headOption match { case Some(accTxt: Text) => Text(accTxt.text + eleTxt.text) :: acc.tail case _ => ele :: acc } case _ => ele :: acc } } Elem(pre, lab, md, scp, false, (mergedTextNodes.flatMap(trimTextZappingEmpty)):_*).asInstanceOf[T] case _ => nodeSeq } /** * Returns true if the passed Any is a Elem. * * @return true if the passed Any is a Elem. */ final def normalizedCanHandle(b: Any): Boolean = b.isInstanceOf[NodeSeq] /** * Normalizes the passed object if it is a Elem. * *

* This method returns either: *

* *
    *
  • if the passed object is a Elem, the result of passing that string to normalized
  • *
  • else, the same exact object that was passed *

    * * @return a normalized form of any passed Elem, or the same object if not a Elem. */ final def normalizedOrSame(b: Any): Any = b match { case s: NodeSeq => StreamlinedXml.streamlined[NodeSeq].normalized(s) case _ => b } } } } /** * Companion object that facilitates the importing of StreamlinedXml members as * an alternative to mixing it the trait. One use case is to import StreamlinedXml members so you can use * them in the Scala interpreter. * * @author Bill Venners */ object StreamlinedXml extends StreamlinedXml




© 2015 - 2024 Weber Informatics LLC | Privacy Policy