From 5cabfdaaabef9a05b137d1bf76f6d2e1cd6d886b Mon Sep 17 00:00:00 2001 From: akira-cn Date: Tue, 15 May 2018 13:30:43 +0800 Subject: [PATCH] fix test cases --- example/node/maketest.js | 32 +++++++----------- test/basesprite.js | 6 ++-- test/helpers/index.js | 10 +++--- .../basesprite-bgcolor-green-opacity.src.png | Bin 0 -> 362 bytes test/img-diff/basesprite-bgcolor-red.src.png | Bin 0 -> 364 bytes test/img-diff/basesprite-s1-s2-rotate.src.png | Bin 0 -> 990 bytes test/img/basesprite-bgcolor-green-opacity.png | Bin 362 -> 362 bytes test/img/basesprite-bgcolor-red.png | Bin 364 -> 364 bytes test/img/basesprite-s1-s2-rotate.png | Bin 1017 -> 990 bytes test/img/label-48px-Arial.png | Bin 12430 -> 9218 bytes 10 files changed, 22 insertions(+), 26 deletions(-) create mode 100644 test/img-diff/basesprite-bgcolor-green-opacity.src.png create mode 100644 test/img-diff/basesprite-bgcolor-red.src.png create mode 100644 test/img-diff/basesprite-s1-s2-rotate.src.png diff --git a/example/node/maketest.js b/example/node/maketest.js index 3f79102e1..a58da380e 100644 --- a/example/node/maketest.js +++ b/example/node/maketest.js @@ -1,38 +1,32 @@ const {createCanvas} = require('canvas') const fs = require('fs') -const Label = require('../../lib/label').default +const {BaseSprite} = require('sprite-core') -async function drawSprites(canvas, sprites) { +function drawSprites(canvas, sprites) { const {width, height} = canvas, context = canvas.getContext('2d') context.clearRect(0, 0, width, height) for(let i = 0; i < sprites.length; i++) { - /* eslint-disable no-await-in-loop */ - await sprites[i].draw(context, true) - /* eslint-enabel no-await-in-loop */ + sprites[i].connect(context).draw() } return canvas.toBuffer() } -const text1 = new Label('SpriteJS.org 中国') - -text1.attr({ - anchor: 0.5, - pos: [400, 300], - font: '48px Arial', - color: '#fff', - bgcolor: 'blue', - renderMode: 'stroke', - lineHeight: 75, - padding: [0, 50, 0, 50], +const s = new BaseSprite() + +s.attr({ + bgcolor: 'red', + anchor: [0.5, 0.5], + pos: [100, 100], + size: [50, 50], }) -const canvas = createCanvas(800, 600) +const canvas = createCanvas(200, 200) ;(async function () { - const buffer = await drawSprites(canvas, [text1]) - fs.writeFileSync('../../test/img/label-48px-Arial.png', buffer) + const buffer = await drawSprites(canvas, [s]) + fs.writeFileSync('../../test/img/basesprite-bgcolor-red.png', buffer) }()) diff --git a/test/basesprite.js b/test/basesprite.js index 1d2007f08..3622ef23f 100644 --- a/test/basesprite.js +++ b/test/basesprite.js @@ -25,7 +25,7 @@ test('test bgcolor red', async (t) => { s.connect(context).draw() - const isEqual = await compare(canvas, 'basesprite-bgcolor-red.png') + const isEqual = await compare(canvas, 'basesprite-bgcolor-red') t.truthy(isEqual) }) @@ -46,7 +46,7 @@ test('test bgcolor green opacity=0.5', async (t) => { s.connect(context).draw() - const isEqual = await compare(canvas, 'basesprite-bgcolor-green-opacity.png') + const isEqual = await compare(canvas, 'basesprite-bgcolor-green-opacity') t.truthy(isEqual) }) @@ -74,6 +74,6 @@ test('test basesprite-s1-s2-rotate', async (t) => { const canvas = createCanvas(200, 200) drawSprites(canvas, [s1, s2]) - const isEqual = await compare(canvas, 'basesprite-s1-s2-rotate.png') + const isEqual = await compare(canvas, 'basesprite-s1-s2-rotate') t.truthy(isEqual) }) diff --git a/test/helpers/index.js b/test/helpers/index.js index cf136de9c..cb0cea8a5 100644 --- a/test/helpers/index.js +++ b/test/helpers/index.js @@ -14,9 +14,9 @@ export async function createCanvasFromFile(src) { return canvas } -export async function compare(canvas, imgFile) { +export async function compare(canvas, caseId) { const srcData = canvas.toBuffer() - const desCanvas = await createCanvasFromFile(`./test/img/${imgFile}`) + const desCanvas = await createCanvasFromFile(`./test/img/${caseId}.png`) const desData = desCanvas.toBuffer() const N = 32 @@ -26,9 +26,10 @@ export async function compare(canvas, imgFile) { const results = await Promise.all([hash1, hash2]) const dist = hamming(...results) - console.warn(colors.cyan(`Hamming distance between canvas and ${imgFile} should be: ${dist}`)) + console.warn(colors.cyan(`Hamming distance between canvas and ${caseId} is: ${dist}`)) - const diffFile = `./test/img-diff/${imgFile}` + const diffFile = `./test/img-diff/${caseId}.diff.png` + const srcFile = `./test/img-diff/${caseId}.src.png` const width = canvas.width, height = canvas.height @@ -69,6 +70,7 @@ export async function compare(canvas, imgFile) { if(!isEqual) { fs.writeFileSync(diffFile, diffCanvas.toBuffer()) + fs.writeFileSync(srcFile, canvas.toBuffer()) } else if(fs.existsSync(diffFile)) { fs.unlinkSync(diffFile) } diff --git a/test/img-diff/basesprite-bgcolor-green-opacity.src.png b/test/img-diff/basesprite-bgcolor-green-opacity.src.png new file mode 100644 index 0000000000000000000000000000000000000000..72a8cffff6aaa17cfd52568b7b825767600c4184 GIT binary patch literal 362 zcmeAS@N?(olHy`uVBq!ia0vp^CqS5k4M?tyST_$yu_bxCyDjR&4c&gI?L#Lbe)wEKr4Pz#x$!QLv2|HmB5XRkQ7-*|fb@VTqZ o56-eMIVuRypCHo<3=9X3>2=&@N;$qZAQ5DSr>mdKI;Vst050k|;Q#;t literal 0 HcmV?d00001 diff --git a/test/img-diff/basesprite-bgcolor-red.src.png b/test/img-diff/basesprite-bgcolor-red.src.png new file mode 100644 index 0000000000000000000000000000000000000000..8f11a67bc104896aac12839feda8cb36baceaf53 GIT binary patch literal 364 zcmeAS@N?(olHy`uVBq!ia0vp^CqS5k4M?tyST_$yu_bxCyDpx&gMzhbuOv0Hl|@?HKuU1m4? ofytaKO%4hibSKF50z(78HDf>&Qwqx(M;nkKp00i_>zopr0Mh?LKL7v# literal 0 HcmV?d00001 diff --git a/test/img-diff/basesprite-s1-s2-rotate.src.png b/test/img-diff/basesprite-s1-s2-rotate.src.png new file mode 100644 index 0000000000000000000000000000000000000000..322338c85a8572e4ab37d8d975f7c30193c9ac27 GIT binary patch literal 990 zcmeAS@N?(olHy`uVBq!ia0vp^CqS5k4M?tyST_$yu_bxCyDMslcId_2<)*ul{`M`BwJNwiUJw(IEcW zq(Uhtj_$M19$(#GU%zTEXCu#{GMR}UZH@|4-*zbrdDb$m%!mgHyb|(I^?lUg64dXY zl_Bh|GRcZ1C}O&W(!?q16PkV<5$s%|(zdd)SoAJ7SMOr9&kfKIq1?4h*vafi#KX%0dXULXNM4}a%wpb9Cbmx(KYT3-4q z$nx3(&G^f)qODg?Cd-7ZLYLV`ABCv2bEfpKJSN!r#Guh8@fFaHoBj&cXHuf>dLQWj7%U7>gx>+QwckO*xeD-+>rp7yh zCuIxoC{NJc-0vdO&+(-3rkhgVT$W9T-zW(lpUm>9<)({L-(HqY$Db$*9(M#feAC2^ z#e$6{23tMi>i6$f;}i054(@#N^}9ganSb9uKKnB<*;~Hv+HC#$YjGFPmdX4(vRSfx z!nC-U`*jzO9hn^dR8B>@j6=WZ97 zmmDe+7XoeG!ZIn~t;dmx^Bja$i*{Ok67XPKsx0Vk$8>T@h{~fA-U^aW`&?vxRwk@% zczW|{VTIg3&#IvJ#UhFmoF)N1lEe}eFv;Uc;1mb0*Ff!E!XB)1l?2^InN}_dRe7|+ zO+nPO%S9%XbIGQ?KyO(!@*Ftlam0{=NwTAQVh6Ka^t@PE{qyVkvfq=M8yF-S|1&Ih Vo>ozGuTl%7+0)g}Wt~$(69DxsgdzX{ literal 0 HcmV?d00001 diff --git a/test/img/basesprite-bgcolor-green-opacity.png b/test/img/basesprite-bgcolor-green-opacity.png index 8e0112ec3be96c2d62bfe030db07b50d4dd5e375..72a8cffff6aaa17cfd52568b7b825767600c4184 100644 GIT binary patch literal 362 zcmeAS@N?(olHy`uVBq!ia0vp^CqS5k4M?tyST_$yu_bxCyDjR&4c&gI?L#Lbe)wEKr4Pz#x$!QLv2|HmB5XRkQ7-*|fb@VTqZ o56-eMIVuRypCHo<3=9X3>2=&@N;$qZAQ5DSr>mdKI;Vst050k|;Q#;t literal 362 zcmeAS@N?(olHy`uVBq!ia0vp^CqS5k4M?tyST_$yu_bxCyDjR&4c&gI?rh=V1QY4;C9pcXR0w$e3nA2f^4ToumSc)Fi`&T94p ovpHFs927X{PLSyXptc9|^*F_tQk2TvcYzG?boFyt=akR{01$3Li2wiq diff --git a/test/img/basesprite-bgcolor-red.png b/test/img/basesprite-bgcolor-red.png index 4f71e9e1c27e6ff0994731c0c58f7aefcf9404df..8f11a67bc104896aac12839feda8cb36baceaf53 100644 GIT binary patch literal 364 zcmeAS@N?(olHy`uVBq!ia0vp^CqS5k4M?tyST_$yu_bxCyDpx&gMzhbuOv0Hl|@?HKuU1m4? ofytaKO%4hibSKF50z(78HDf>&Qwqx(M;nkKp00i_>zopr0Mh?LKL7v# literal 364 zcmeAS@N?(olHy`uVBq!ia0vp^CqS5k4M?tyST_$yu_bxCyD&t;ucLK6V_fj(RS diff --git a/test/img/basesprite-s1-s2-rotate.png b/test/img/basesprite-s1-s2-rotate.png index 9f18e137411c3b4c69f253f001fdf970fc1a5383..322338c85a8572e4ab37d8d975f7c30193c9ac27 100644 GIT binary patch delta 862 zcmV-k1EKu+2i^yeHcpdCL_t(|obBB`ZWCz$$KltABcy_gtyZg4U~iEF{jB>>h zi6lRPWRg3MNF;d)B!g0ML?X#YAc>WZBN9m-0!gS=9Fa)U6G$Spc9SuE>NF@CTq=T`<5s9QbfwVNXe>ftMbR&=!R_B)| zV~isbNqf(04;YJ-?{n1jf8aeHm7f!LkOrm_NA&I0?KRcjF$MxTU}|who5kW(B!>xP zkEzBHiR3VWJYni_L?YQwAUn(@jz}a=6UYN|iz5=rZUWgd*Ek}PJSLDkbB`ku$$bI| z;&@0Tzs)|7H*eQRf8uy-vsj$IdAmNUy`#3-2lDy-@;cmvi`qK|=O$cye!sk~J)^eS z2NFUE>vyZKBH3~iF4pf>Uu(}80)gBS$sKXrBakh#k3<}g2;_m;Mk0=#1hT{IA`!=v z1oDL0L?Vv81hU8EBN4|z0y$u^k%*%afiy6+NM3)xyCx12e@H`9iRAV75MIpw_wnZZ zkz-3Aj@Fwmf7V{n&2}9A#IqT9kd|It-+s}?#+{=ZfpjpoNW{^dKsp*rB;x2tAUzB{ z5^?k=ke-Gbi8#^_NCHEPL>%b|B$1&+B962Kl2GkP#F3sr5~~%7IPwrk2BjkrM?M0{ zq*Ns0$V(s@X624V9Qk=*t$^j()p2+p{z-aL?{gF(kV2A1B93ANQc#je#8H$$3hNb# zIEoWU1)U-hM->98q*Wy1s74?aHHt(WRSBfBy^)BcI)Mzp&Pc>D2m%?1dy$9(9$TJW o9WT$Wj%)9eu>&v}02qP)0HZ^ecyiu(DgXcg07*qoM6N<$f_dhDVgLXD delta 893 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 OaQ3u^Q~e)TZv7wm*z$P* literal 12430 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 QfBxj*0~5X4`!28lKlJNqAOHXW