     }
 
     func testRotate() {
+        let radians = { (angle: CGFloat) -> CGFloat in
+            return .pi * angle / 360
+        }
 
+        let testCases: [UInt: TestCase] = [
+            #line: TestCase(
+                description: "Rotate by 90 degrees",
+                transform: .rotate(angle: radians(90)),
+                expect: CGAffineTransform(a: cos(radians(90)), b: -sin(radians(90)), c: sin(radians(90)), d: cos(radians(90)), tx: 0.0, ty: 0.0)
+            ),
+            #line: TestCase(
+                description: "Rotate by 360 degrees",
+                transform: .rotate(angle: radians(360)),
+                expect: CGAffineTransform(a: cos(radians(360)), b: -sin(radians(360)), c: sin(radians(360)), d: cos(radians(360)), tx: 0.0, ty: 0.0)
+            ),
+            #line: TestCase(
+                description: "Rotate by -90 degrees",
+                transform: .rotate(angle: radians(-90)),
+                expect: CGAffineTransform(a: cos(radians(-90)), b: -sin(radians(-90)), c: sin(radians(-90)), d: cos(radians(-90)), tx: 0.0, ty: 0.0)
+            ),
+        ]
+
+        check(testCases: testCases)
     }
 
     func check(testCases: [UInt: TestCase]) {
         _ = testCases.map { (line, testCase) in
             let view = ProcessingView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
 
-            let translateDelegateSpy = ProcessingViewDelegateTransformSpy(
+            let transformDelegateSpy = ProcessingViewDelegateTransformSpy(
                 exception: expectation(description: testCase.description),
                 view: view,
-                x: testCase.transform.x,
-                y: testCase.transform.y
+                transform: testCase.transform
             )
 
-            view.delegate = translateDelegateSpy
+            view.delegate = transformDelegateSpy
             waitForExpectations(timeout: 100)
 
-            let actual = translateDelegateSpy.context?.ctm
-            let expected = testCase.expect
-            XCTAssertEqual(actual, expected, String(line))
+            let actual = transformDelegateSpy.context?.ctm
+
+            switch testCase.transform {
+            // Multiply translate(0.0, 100.0), scale(1.0, -1.0) and expect together for coordinate system
+            case .translate(_, _):
+                let expected = CGAffineTransform(a: 1.0, b: 0.0, c: -0.0, d: -1.0, tx: 0.0, ty: 100.0).concatenating(testCase.expect)
+                XCTAssertEqual(actual, expected, String(line))
+            case .rotate(_):
+                let expected = CGAffineTransform(a: 1.0, b: 0.0, c: -0.0, d: -1.0, tx: 0.0, ty: 0.0).concatenating(testCase.expect.concatenating(CGAffineTransform(a: 1.0, b: 0.0, c: 0.0, d: 1.0, tx: 0.0, ty: 100.0)))
+                XCTAssertEqual(actual, expected, String(line))
+            }
         }
     }
 
     struct TestCase {
         let description: String
-        let transform: (x: CGFloat, y: CGFloat)
+        let transform: Transform
         let expect: CGAffineTransform
 
         init(
             description: String,
-            transform: (x: CGFloat, y: CGFloat),
+            transform: Transform,
             expect: CGAffineTransform
             ) {
             self.description = description

                       | a  b  0 |
 [x' y' 1] = [x y 1] × | c  d  0 |
                       | tx ty 1 |
 */

class ProcessingViewDelegateTransformSpy: ProcessingViewDelegate {
    private let exception: XCTestExpectation
    private let view: ProcessingView
    private let x: CGFloat
    private let y: CGFloat
    private(set) var context: CGContext?

    init(exception: XCTestExpectation, view: ProcessingView, x: CGFloat, y: CGFloat) {
        self.exception = exception
        self.view = view
        self.x = x
        self.y = y
    }

    func setup() {
        self.view.translate(x, y)
        self.record(UIGraphicsGetCurrentContext())
        exception.fulfill()
    }

        let testCases: [UInt: TestCase] = [
            #line: TestCase(
                description: "Move 100pt to the right",
                transform: .translate(x: 100.0, y: 0.0),
                expect: CGAffineTransform(a: 1.0, b: 0.0, c: 0.0, d: 1.0, tx: 100.0, ty: 0.0)
            ),
            #line: TestCase(
                description: "Move 50pt to the bottom",
                transform: .translate(x: 0.0, y: 50.0),
                expect: CGAffineTransform(a: 1.0, b: 0.0, c: 0.0, d: 1.0, tx: 0.0, ty: -50.0)
            ),
            #line: TestCase(
                description: "Move 40pt to the left, 20pt to the top",
                transform: .translate(x: -40.0, y: -20.0),
                expect: CGAffineTransform(a: 1.0, b: 0.0, c: 0.0, d: 1.0, tx: -40.0, ty: 20.0)
            ),
        ]

