import Context from './../../src/lib/context' ; import util from './../../src' ; import { getData } from './data' ; const { deepClone } = util . data ; describe ( '@idraw/board: src/lib/context' , ( ) => { const options = { width : 600 , height : 400 , contextWidth : 1000 , contextHeight : 900 , devicePixelRatio : 2 } ; test ( 'Context' , async ( ) => { const opts = deepClone ( options ) ; const canvas = document . createElement ( 'canvas' ) ; canvas . width = opts . contextWidth ; canvas . height = opts . contextHeight ; const ctx2d = canvas . getContext ( '2d' ) as CanvasRenderingContext2D ; const ctx = new Context ( ctx2d , opts ) ; const data = getData ( ) ; ctx . clearRect ( 0 , 0 , opts . contextWidth , opts . contextHeight ) ; ctx . setFillStyle ( '#ffffff' ) ; ctx . fillRect ( 0 , 0 , opts . contextWidth , opts . contextHeight ) ; data . elements . forEach ( ele => { ctx . setFillStyle ( ele . desc . color ) ; ctx . fillRect ( ele . x , ele . y , ele . w , ele . h ) ; } ) ; const calls = ctx2d . __getDrawCalls ( ) ; expect ( calls ) . toMatchSnapshot ( ) ; } ) ; test ( 'Context.getSize' , async ( ) => { const opts = deepClone ( options ) ; const canvas = document . createElement ( 'canvas' ) ; canvas . width = opts . contextWidth ; canvas . height = opts . contextHeight ; const ctx2d = canvas . getContext ( '2d' ) as CanvasRenderingContext2D ; const ctx = new Context ( ctx2d , opts ) ; expect ( ctx . getSize ( ) ) . toStrictEqual ( opts ) ; } ) ; test ( 'Context.resetSize' , async ( ) => { const opts = deepClone ( options ) ; const canvas = document . createElement ( 'canvas' ) ; canvas . width = opts . contextWidth ; canvas . height = opts . contextHeight ; const ctx2d = canvas . getContext ( '2d' ) as CanvasRenderingContext2D ; const newOpts = { width : 601 , height : 401 , contextWidth : 1001 , contextHeight : 901 , devicePixelRatio : 3 , } ; const ctx = new Context ( ctx2d , opts ) ; ctx . resetSize ( newOpts ) ; expect ( ctx . getSize ( ) ) . toStrictEqual ( newOpts ) ; } ) ; test ( 'Context.calcDeviceNum' , async ( ) => { const opts = deepClone ( options ) ; const canvas = document . createElement ( 'canvas' ) ; canvas . width = opts . contextWidth ; canvas . height = opts . contextHeight ; const ctx2d = canvas . getContext ( '2d' ) as CanvasRenderingContext2D ; const ctx = new Context ( ctx2d , opts ) ; const num = 100 ; expect ( ctx . calcDeviceNum ( num ) ) . toStrictEqual ( opts . devicePixelRatio * num ) ; } ) ; test ( 'Context.calcScreenNum' , async ( ) => { const opts = deepClone ( options ) ; const canvas = document . createElement ( 'canvas' ) ; canvas . width = opts . contextWidth ; canvas . height = opts . contextHeight ; const ctx2d = canvas . getContext ( '2d' ) as CanvasRenderingContext2D ; const ctx = new Context ( ctx2d , opts ) ; const num = 100 ; expect ( ctx . calcScreenNum ( num ) ) . toStrictEqual ( num / opts . devicePixelRatio ) ; } ) ; test ( 'Context.setTransform' , async ( ) => { const opts = deepClone ( options ) ; const canvas = document . createElement ( 'canvas' ) ; canvas . width = opts . contextWidth ; canvas . height = opts . contextHeight ; const ctx2d = canvas . getContext ( '2d' ) as CanvasRenderingContext2D ; const ctx = new Context ( ctx2d , opts ) ; const transform = { scale : 2 , scrollX : 100 , scrollY : - 200 , } ; ctx . setTransform ( deepClone ( transform ) ) ; expect ( ctx . getTransform ( ) ) . toStrictEqual ( deepClone ( transform ) ) ; } ) ; test ( 'Context.getTransform' , async ( ) => { const opts = deepClone ( options ) ; const canvas = document . createElement ( 'canvas' ) ; canvas . width = opts . contextWidth ; canvas . height = opts . contextHeight ; const ctx2d = canvas . getContext ( '2d' ) as CanvasRenderingContext2D ; const ctx = new Context ( ctx2d , opts ) ; expect ( ctx . getTransform ( ) ) . toStrictEqual ( { scale : 1 , scrollX : 0 , scrollY : 0 , } ) ; } ) ; test ( 'Context.setFillStyle' , async ( ) => { const opts = deepClone ( options ) ; const canvas = document . createElement ( 'canvas' ) ; canvas . width = opts . contextWidth ; canvas . height = opts . contextHeight ; const ctx2d = canvas . getContext ( '2d' ) as CanvasRenderingContext2D ; const ctx = new Context ( ctx2d , opts ) ; const color = '#f0f0f0' ; ctx . setFillStyle ( color ) ; ctx . fillRect ( 0 , 0 , opts . contextWidth , opts . contextHeight ) ; expect ( ctx2d . fillStyle ) . toStrictEqual ( color ) ; } ) ; test ( 'Context.fill' , async ( ) => { const opts = deepClone ( options ) ; const canvas = document . createElement ( 'canvas' ) ; canvas . width = opts . contextWidth ; canvas . height = opts . contextHeight ; const ctx2d = canvas . getContext ( '2d' ) as CanvasRenderingContext2D ; const ctx = new Context ( ctx2d , opts ) ; ctx . fill ( ) ; const calls = ctx2d . __getDrawCalls ( ) ; expect ( calls ) . toMatchSnapshot ( ) ; } ) ; test ( 'Context.arc' , async ( ) => { const opts = deepClone ( options ) ; const canvas = document . createElement ( 'canvas' ) ; canvas . width = opts . contextWidth ; canvas . height = opts . contextHeight ; const ctx2d = canvas . getContext ( '2d' ) as CanvasRenderingContext2D ; const ctx = new Context ( ctx2d , opts ) ; ctx . arc ( 70 , 80 , 50 , 0 , Math . PI * 2 , true ) ; ctx . fill ( ) ; const calls = ctx2d . __getDrawCalls ( ) ; expect ( calls ) . toMatchSnapshot ( ) ; } ) ; test ( 'Context.rect' , async ( ) => { const opts = deepClone ( options ) ; const canvas = document . createElement ( 'canvas' ) ; canvas . width = opts . contextWidth ; canvas . height = opts . contextHeight ; const ctx2d = canvas . getContext ( '2d' ) as CanvasRenderingContext2D ; const ctx = new Context ( ctx2d , opts ) ; ctx . rect ( 10 , 20 , 100 , 200 ) ; ctx . fill ( ) ; const calls = ctx2d . __getDrawCalls ( ) ; expect ( calls ) . toMatchSnapshot ( ) ; } ) ; test ( 'Context.fillRect' , async ( ) => { const opts = deepClone ( options ) ; const canvas = document . createElement ( 'canvas' ) ; canvas . width = opts . contextWidth ; canvas . height = opts . contextHeight ; const ctx2d = canvas . getContext ( '2d' ) as CanvasRenderingContext2D ; const ctx = new Context ( ctx2d , opts ) ; ctx . fillRect ( 10 , 20 , 80 , 100 ) ; const calls = ctx2d . __getDrawCalls ( ) ; expect ( calls ) . toMatchSnapshot ( ) ; } ) ; test ( 'Context.clearRect' , async ( ) => { const opts = deepClone ( options ) ; const canvas = document . createElement ( 'canvas' ) ; canvas . width = opts . contextWidth ; canvas . height = opts . contextHeight ; const ctx2d = canvas . getContext ( '2d' ) as CanvasRenderingContext2D ; const ctx = new Context ( ctx2d , opts ) ; ctx . clearRect ( 0 , 0 , opts . contextWidth , opts . contextHeight ) ; const calls = ctx2d . __getDrawCalls ( ) ; expect ( calls ) . toMatchSnapshot ( ) ; } ) ; test ( 'Context.beginPath' , async ( ) => { const opts = deepClone ( options ) ; const canvas = document . createElement ( 'canvas' ) ; canvas . width = opts . contextWidth ; canvas . height = opts . contextHeight ; const ctx2d = canvas . getContext ( '2d' ) as CanvasRenderingContext2D ; const ctx = new Context ( ctx2d , opts ) ; ctx . beginPath ( ) ; ctx . fill ( ) ; const calls = ctx2d . __getDrawCalls ( ) ; expect ( calls ) . toMatchSnapshot ( ) ; } ) ; test ( 'Context.closePath' , async ( ) => { const opts = deepClone ( options ) ; const canvas = document . createElement ( 'canvas' ) ; canvas . width = opts . contextWidth ; canvas . height = opts . contextHeight ; const ctx2d = canvas . getContext ( '2d' ) as CanvasRenderingContext2D ; const ctx = new Context ( ctx2d , opts ) ; ctx . closePath ( ) ; ctx . fill ( ) ; const calls = ctx2d . __getDrawCalls ( ) ; expect ( calls ) . toMatchSnapshot ( ) ; } ) ; test ( 'Context.lineTo' , async ( ) => { const opts = deepClone ( options ) ; const canvas = document . createElement ( 'canvas' ) ; canvas . width = opts . contextWidth ; canvas . height = opts . contextHeight ; const ctx2d = canvas . getContext ( '2d' ) as CanvasRenderingContext2D ; const ctx = new Context ( ctx2d , opts ) ; ctx . lineTo ( 10 , 20 ) ; ctx . fill ( ) ; const calls = ctx2d . __getDrawCalls ( ) ; expect ( calls ) . toMatchSnapshot ( ) ; } ) ; test ( 'Context.moveTo' , async ( ) => { const opts = deepClone ( options ) ; const canvas = document . createElement ( 'canvas' ) ; canvas . width = opts . contextWidth ; canvas . height = opts . contextHeight ; const ctx2d = canvas . getContext ( '2d' ) as CanvasRenderingContext2D ; const ctx = new Context ( ctx2d , opts ) ; ctx . moveTo ( 10 , 20 ) ; ctx . fill ( ) ; const calls = ctx2d . __getDrawCalls ( ) ; expect ( calls ) . toMatchSnapshot ( ) ; } ) ; test ( 'Context.arcTo' , async ( ) => { const opts = deepClone ( options ) ; const canvas = document . createElement ( 'canvas' ) ; canvas . width = opts . contextWidth ; canvas . height = opts . contextHeight ; const ctx2d = canvas . getContext ( '2d' ) as CanvasRenderingContext2D ; const ctx = new Context ( ctx2d , opts ) ; ctx . arcTo ( 50 , 50 , 100 , 100 , Math . PI * 2 ) ; ctx . fill ( ) ; const calls = ctx2d . __getDrawCalls ( ) ; expect ( calls ) . toMatchSnapshot ( ) ; } ) ; test ( 'Context.setLineWidth' , async ( ) => { const opts = deepClone ( options ) ; const canvas = document . createElement ( 'canvas' ) ; canvas . width = opts . contextWidth ; canvas . height = opts . contextHeight ; const lineWidth = 12 ; const ctx2d = canvas . getContext ( '2d' ) as CanvasRenderingContext2D ; const ctx = new Context ( ctx2d , opts ) ; ctx . setLineWidth ( lineWidth ) ; expect ( ctx2d . lineWidth ) . toStrictEqual ( lineWidth * opts . devicePixelRatio ) ; } ) ; test ( 'Context.setLineDash' , async ( ) => { const opts = deepClone ( options ) ; const canvas = document . createElement ( 'canvas' ) ; canvas . width = opts . contextWidth ; canvas . height = opts . contextHeight ; const lineDash = [ 10 , 20 ] ; const ctx2d = canvas . getContext ( '2d' ) as CanvasRenderingContext2D ; const ctx = new Context ( ctx2d , opts ) ; ctx . setLineDash ( lineDash ) ; expect ( ctx2d . getLineDash ( ) ) . toStrictEqual ( lineDash . map ( n => n * opts . devicePixelRatio ) ) ; } ) ; test ( 'Context.setStrokeStyle' , async ( ) => { const opts = deepClone ( options ) ; const canvas = document . createElement ( 'canvas' ) ; canvas . width = opts . contextWidth ; canvas . height = opts . contextHeight ; const ctx2d = canvas . getContext ( '2d' ) as CanvasRenderingContext2D ; const ctx = new Context ( ctx2d , opts ) ; const color = '#f0f0f0' ; ctx . setStrokeStyle ( color ) ; ctx . fillRect ( 0 , 0 , opts . contextWidth , opts . contextHeight ) ; expect ( ctx2d . strokeStyle ) . toStrictEqual ( color ) ; } ) ; test ( 'Context.isPointInPath' , async ( ) => { const opts = deepClone ( options ) ; const canvas = document . createElement ( 'canvas' ) ; canvas . width = opts . contextWidth ; canvas . height = opts . contextHeight ; const ctx2d = canvas . getContext ( '2d' ) as CanvasRenderingContext2D ; const ctx = new Context ( ctx2d , opts ) ; const x = 50 ; const y = 50 ; const w = 50 ; const h = 50 ; ctx . beginPath ( ) ; ctx . moveTo ( x , y ) ; ctx . lineTo ( x + w , y ) ; ctx . lineTo ( x + w , y + h ) ; ctx . lineTo ( x , y + h ) ; ctx . lineTo ( x , y ) ; ctx . closePath ( ) ; const calls = ctx2d . __getDrawCalls ( ) ; expect ( ctx . isPointInPath ( 51 , 51 ) ) . toStrictEqual ( ctx2d . isPointInPath ( 60 * opts . devicePixelRatio , 60 * opts . devicePixelRatio ) ) ; } ) ; test ( 'Context.isPointInPathWithoutScroll' , async ( ) => { const opts = deepClone ( options ) ; const canvas = document . createElement ( 'canvas' ) ; canvas . width = opts . contextWidth ; canvas . height = opts . contextHeight ; const ctx2d = canvas . getContext ( '2d' ) as CanvasRenderingContext2D ; const ctx = new Context ( ctx2d , opts ) ; ctx . setTransform ( { scale : 2 , scrollX : 10 , scrollY : 10 , } ) ; ctx . beginPath ( ) ; ctx . rect ( 50 , 50 , 100 , 100 ) ; ctx . closePath ( ) ; const calls = ctx2d . __getDrawCalls ( ) ; expect ( ctx . isPointInPathWithoutScroll ( 51 , 51 ) ) . toStrictEqual ( ctx2d . isPointInPath ( 60 * opts . devicePixelRatio , 60 * opts . devicePixelRatio ) ) ; } ) ; test ( 'Context.setStrokeStyle' , async ( ) => { const opts = deepClone ( options ) ; const canvas = document . createElement ( 'canvas' ) ; canvas . width = opts . contextWidth ; canvas . height = opts . contextHeight ; const ctx2d = canvas . getContext ( '2d' ) as CanvasRenderingContext2D ; const ctx = new Context ( ctx2d , opts ) ; const color = '#f0f0f0' ; ctx . setStrokeStyle ( color ) ; expect ( ctx2d . strokeStyle ) . toStrictEqual ( color ) ; } ) ; test ( 'Context.stroke' , async ( ) => { const opts = deepClone ( options ) ; const canvas = document . createElement ( 'canvas' ) ; canvas . width = opts . contextWidth ; canvas . height = opts . contextHeight ; const ctx2d = canvas . getContext ( '2d' ) as CanvasRenderingContext2D ; const ctx = new Context ( ctx2d , opts ) ; ctx . rect ( 10 , 20 , 100 , 200 ) ; ctx . stroke ( ) ; const calls = ctx2d . __getDrawCalls ( ) ; expect ( calls ) . toMatchSnapshot ( ) ; } ) ; test ( 'Context.translate' , async ( ) => { const opts = deepClone ( options ) ; const canvas = document . createElement ( 'canvas' ) ; canvas . width = opts . contextWidth ; canvas . height = opts . contextHeight ; const ctx2d = canvas . getContext ( '2d' ) as CanvasRenderingContext2D ; const ctx = new Context ( ctx2d , opts ) ; const x = 50 ; const y = 60 ; ctx . translate ( x , y ) ; ctx . rect ( 10 , 20 , 100 , 200 ) ; ctx . stroke ( ) ; ctx . translate ( - x , - y ) ; const calls = ctx2d . __getDrawCalls ( ) ; expect ( calls ) . toMatchSnapshot ( ) ; } ) ; test ( 'Context.rotate' , async ( ) => { const opts = deepClone ( options ) ; const canvas = document . createElement ( 'canvas' ) ; canvas . width = opts . contextWidth ; canvas . height = opts . contextHeight ; const ctx2d = canvas . getContext ( '2d' ) as CanvasRenderingContext2D ; const ctx = new Context ( ctx2d , opts ) ; const radian = Math . PI / 6 ; ctx . rotate ( radian ) ; ctx . rect ( 10 , 20 , 100 , 200 ) ; ctx . stroke ( ) ; ctx . rotate ( - radian ) ; const calls = ctx2d . __getDrawCalls ( ) ; expect ( calls ) . toMatchSnapshot ( ) ; } ) ; test ( 'Context.drawImage' , async ( ) => { const opts = deepClone ( options ) ; const canvas = document . createElement ( 'canvas' ) ; canvas . width = opts . contextWidth ; canvas . height = opts . contextHeight ; const ctx2d = canvas . getContext ( '2d' ) as CanvasRenderingContext2D ; const ctx = new Context ( ctx2d , opts ) ; const img = new Image ( ) ; const dx = 11 ; const dy = 12 ; const dw = 51 ; const dh = 52 ; const sx = 61 ; const sy = 62 ; const sw = 101 ; const sh = 102 ; ctx . drawImage ( img , dx , dy ) ; ctx . drawImage ( img , dx , dy , dw , dh ) ; ctx . drawImage ( img , sx , sy , sw , sh , dx , dy , dw , dh ) ; const calls = ctx2d . __getDrawCalls ( ) ; expect ( calls ) . toMatchSnapshot ( ) ; } ) ; test ( 'Context.createPattern' , async ( ) => { const opts = deepClone ( options ) ; const canvas = document . createElement ( 'canvas' ) ; canvas . width = opts . contextWidth ; canvas . height = opts . contextHeight ; const ctx2d = canvas . getContext ( '2d' ) as CanvasRenderingContext2D ; const ctx = new Context ( ctx2d , opts ) ; const img = new Image ( ) ; const pattern = ctx . createPattern ( img , 'repeat' ) as CanvasPattern ; ctx . setFillStyle ( pattern ) ; ctx . fillRect ( 0 , 0 , 300 , 300 ) ; const calls = ctx2d . __getDrawCalls ( ) ; expect ( ctx2d . fillStyle ) . toStrictEqual ( pattern ) ; expect ( calls ) . toMatchSnapshot ( ) ; } ) ; test ( 'Context.measureText' , async ( ) => { const opts = deepClone ( options ) ; const canvas = document . createElement ( 'canvas' ) ; canvas . width = opts . contextWidth ; canvas . height = opts . contextHeight ; const ctx2d = canvas . getContext ( '2d' ) as CanvasRenderingContext2D ; const ctx = new Context ( ctx2d , opts ) ; ctx . setFont ( { fontSize : 20 } ) ; const size = ctx . measureText ( 'Hello World!' ) ; expect ( size . width ) . toStrictEqual ( 12 ) ; } ) ; test ( 'Context.setTextAlign' , async ( ) => { const opts = deepClone ( options ) ; const canvas = document . createElement ( 'canvas' ) ; canvas . width = opts . contextWidth ; canvas . height = opts . contextHeight ; const ctx2d = canvas . getContext ( '2d' ) as CanvasRenderingContext2D ; const ctx = new Context ( ctx2d , opts ) ; const textAlign = 'center' ; ctx . setTextAlign ( textAlign ) ; ctx . fillRect ( 0 , 0 , opts . contextWidth , opts . contextHeight ) ; expect ( ctx2d . textAlign ) . toStrictEqual ( textAlign ) ; } ) ; test ( 'Context.fillText' , async ( ) => { const opts = deepClone ( options ) ; const canvas = document . createElement ( 'canvas' ) ; canvas . width = opts . contextWidth ; canvas . height = opts . contextHeight ; const ctx2d = canvas . getContext ( '2d' ) as CanvasRenderingContext2D ; const ctx = new Context ( ctx2d , opts ) ; ctx . fillText ( 'Hello world' , 50 , 100 ) ; const calls = ctx2d . __getDrawCalls ( ) ; expect ( calls ) . toMatchSnapshot ( ) ; } ) ; test ( 'Context.setFont' , async ( ) => { const opts = deepClone ( options ) ; const canvas = document . createElement ( 'canvas' ) ; canvas . width = opts . contextWidth ; canvas . height = opts . contextHeight ; const ctx2d = canvas . getContext ( '2d' ) as CanvasRenderingContext2D ; const ctx = new Context ( ctx2d , opts ) ; const fontSize = 22 ; const fontFamily = 'Hello' ; const fontWeight = 'bold' ; ctx . setFont ( { fontSize , fontFamily , fontWeight } ) ; expect ( ctx2d . font ) . toStrictEqual ( [ fontWeight , ( fontSize * opts . devicePixelRatio ) + 'px' , fontFamily ] . join ( ' ' ) ) ; } ) ; test ( 'Context.setTextBaseline' , async ( ) => { const opts = deepClone ( options ) ; const canvas = document . createElement ( 'canvas' ) ; canvas . width = opts . contextWidth ; canvas . height = opts . contextHeight ; const ctx2d = canvas . getContext ( '2d' ) as CanvasRenderingContext2D ; const ctx = new Context ( ctx2d , opts ) ; const textBaseline = 'bottom' ; ctx . setTextBaseline ( textBaseline ) ; expect ( ctx2d . textBaseline ) . toStrictEqual ( textBaseline ) ; } ) ; test ( 'Context.setGlobalAlpha' , async ( ) => { const opts = deepClone ( options ) ; const canvas = document . createElement ( 'canvas' ) ; canvas . width = opts . contextWidth ; canvas . height = opts . contextHeight ; const ctx2d = canvas . getContext ( '2d' ) as CanvasRenderingContext2D ; const ctx = new Context ( ctx2d , opts ) ; const globalAlpha = 0.45 ; ctx . setGlobalAlpha ( globalAlpha ) ; expect ( ctx2d . globalAlpha ) . toStrictEqual ( globalAlpha ) ; } ) ; test ( 'Context.save' , async ( ) => { const opts = deepClone ( options ) ; const canvas = document . createElement ( 'canvas' ) ; canvas . width = opts . contextWidth ; canvas . height = opts . contextHeight ; const ctx2d = canvas . getContext ( '2d' ) as CanvasRenderingContext2D ; const ctx = new Context ( ctx2d , opts ) ; ctx . save ( ) ; ctx . setFillStyle ( '#f0f0f0' ) ; ctx . fillRect ( 10 , 10 , 100 , 100 ) ; ctx . restore ( ) ; ctx . fillRect ( 150 , 75 , 100 , 100 ) ; const calls = ctx2d . __getDrawCalls ( ) ; expect ( calls ) . toMatchSnapshot ( ) ; } ) ; test ( 'Context.restore' , async ( ) => { const opts = deepClone ( options ) ; const canvas = document . createElement ( 'canvas' ) ; canvas . width = opts . contextWidth ; canvas . height = opts . contextHeight ; const ctx2d = canvas . getContext ( '2d' ) as CanvasRenderingContext2D ; const ctx = new Context ( ctx2d , opts ) ; ctx . save ( ) ; ctx . setFillStyle ( '#f0f0f0' ) ; ctx . fillRect ( 10 , 10 , 100 , 100 ) ; ctx . restore ( ) ; ctx . fillRect ( 150 , 75 , 100 , 100 ) ; const calls = ctx2d . __getDrawCalls ( ) ; expect ( calls ) . toMatchSnapshot ( ) ; } ) ; test ( 'Context.scale' , async ( ) => { const opts = deepClone ( options ) ; const canvas = document . createElement ( 'canvas' ) ; canvas . width = opts . contextWidth ; canvas . height = opts . contextHeight ; const ctx2d = canvas . getContext ( '2d' ) as CanvasRenderingContext2D ; const ctx = new Context ( ctx2d , opts ) ; const scaleX = 2 ; const scaleY = 3 ; ctx . scale ( scaleX , scaleY ) ; ctx . rect ( 10 , 20 , 100 , 200 ) ; ctx . stroke ( ) ; const calls = ctx2d . __getDrawCalls ( ) ; expect ( calls ) . toMatchSnapshot ( ) ; } ) ; } ) ;