2013-10-30 19:26:07 +00:00
/* vim: set ts=2: */
2014-03-29 22:53:15 +00:00
var X ;
2014-06-29 18:29:45 +00:00
var modp = './' ;
//var modp = 'xlsx';
2013-10-30 19:26:07 +00:00
var fs = require ( 'fs' ) , assert = require ( 'assert' ) ;
2014-06-29 18:29:45 +00:00
describe ( 'source' , function ( ) { it ( 'should load' , function ( ) { X = require ( modp ) ; } ) ; } ) ;
2014-02-15 05:08:18 +00:00
2014-05-16 00:33:34 +00:00
var opts = { cellNF : true } ;
2014-06-05 07:06:20 +00:00
if ( process . env . WTF ) {
opts . WTF = true ;
opts . cellStyles = true ;
}
2014-05-16 00:33:34 +00:00
var fullex = [ ".xlsb" , ".xlsm" , ".xlsx" ] ;
2014-10-26 05:26:18 +00:00
var ex = fullex . slice ( ) ; ex . push ( ".ods" ) ;
2014-05-16 00:33:34 +00:00
if ( process . env . FMTS === "full" ) process . env . FMTS = ex . join ( ":" ) ;
2014-02-13 06:22:42 +00:00
if ( process . env . FMTS ) ex = process . env . FMTS . split ( ":" ) . map ( function ( x ) { return x [ 0 ] === "." ? x : "." + x ; } ) ;
2014-02-12 06:09:42 +00:00
var exp = ex . map ( function ( x ) { return x + ".pending" ; } ) ;
2014-10-10 02:22:38 +00:00
function test _file ( x ) { return ex . indexOf ( x . substr ( - 5 ) ) >= 0 || exp . indexOf ( x . substr ( - 13 ) ) >= 0 || ex . indexOf ( x . substr ( - 4 ) ) >= 0 || exp . indexOf ( x . substr ( - 12 ) ) >= 0 ; }
2014-01-28 16:38:02 +00:00
var files = ( fs . existsSync ( 'tests.lst' ) ? fs . readFileSync ( 'tests.lst' , 'utf-8' ) . split ( "\n" ) : fs . readdirSync ( 'test_files' ) ) . filter ( test _file ) ;
2014-04-03 22:51:54 +00:00
var fileA = ( fs . existsSync ( 'testA.lst' ) ? fs . readFileSync ( 'testA.lst' , 'utf-8' ) . split ( "\n" ) : [ ] ) . filter ( test _file ) ;
2013-10-30 19:26:07 +00:00
2014-01-23 06:20:19 +00:00
/* Excel enforces 31 character sheet limit, although technical file limit is 255 */
function fixsheetname ( x ) { return x . substr ( 0 , 31 ) ; }
2014-06-29 18:29:45 +00:00
function stripbom ( x ) { return x . replace ( /^\ufeff/ , "" ) ; }
function fixcsv ( x ) { return stripbom ( x ) . replace ( /\t/g , "," ) . replace ( /#{255}/g , "" ) . replace ( /"/g , "" ) . replace ( /[\n\r]+/g , "\n" ) . replace ( /\n*$/ , "" ) ; }
2014-05-03 18:51:10 +00:00
function fixjson ( x ) { return x . replace ( /[\r\n]+$/ , "" ) ; }
2013-12-27 03:15:16 +00:00
2014-02-15 05:08:18 +00:00
var dir = "./test_files/" ;
2014-03-29 22:53:15 +00:00
var paths = {
cp1 : dir + 'custom_properties.xlsx' ,
cp2 : dir + 'custom_properties.xlsb' ,
2014-05-29 22:30:03 +00:00
css1 : dir + 'cell_style_simple.xlsx' ,
css2 : dir + 'cell_style_simple.xlsb' ,
2014-03-29 22:53:15 +00:00
cst1 : dir + 'comments_stress_test.xlsx' ,
cst2 : dir + 'comments_stress_test.xlsb' ,
fst1 : dir + 'formula_stress_test.xlsx' ,
fst2 : dir + 'formula_stress_test.xlsb' ,
2014-10-26 05:26:18 +00:00
fst3 : dir + 'formula_stress_test.ods' ,
2014-03-29 22:53:15 +00:00
fstb : dir + 'formula_stress_test.xlsb' ,
2014-04-15 09:04:03 +00:00
hl1 : dir + 'hyperlink_stress_test_2011.xlsx' ,
hl2 : dir + 'hyperlink_stress_test_2011.xlsb' ,
2014-03-29 22:53:15 +00:00
lon1 : dir + 'LONumbers.xlsx' ,
mc1 : dir + 'merge_cells.xlsx' ,
mc2 : dir + 'merge_cells.xlsb' ,
2014-10-26 05:26:18 +00:00
mc3 : dir + 'merge_cells.ods' ,
2014-03-29 22:53:15 +00:00
nf1 : dir + 'number_format.xlsm' ,
nf2 : dir + 'number_format.xlsb' ,
2014-10-26 05:26:18 +00:00
dt1 : dir + 'xlsx-stream-d-date-cell.xlsx' ,
dt2 : dir + 'xlsx-stream-d-date-cell.xlsb' ,
2014-03-29 22:53:15 +00:00
swc1 : dir + 'apachepoi_SimpleWithComments.xlsx' ,
swc2 : dir + '2013/apachepoi_SimpleWithComments.xlsx.xlsb'
} ;
var N1 = 'XLSX' ;
var N2 = 'XLSB' ;
2014-05-16 00:33:34 +00:00
function parsetest ( x , wb , full , ext ) {
ext = ( ext ? " [" + ext + "]" : "" ) ;
2014-05-29 22:30:03 +00:00
if ( ! full && ext ) return ;
2014-05-16 00:33:34 +00:00
describe ( x + ext + ' should have all bits' , function ( ) {
2014-02-15 05:08:18 +00:00
var sname = dir + '2011/' + x + '.sheetnames' ;
2013-10-30 19:26:07 +00:00
it ( 'should have all sheets' , function ( ) {
wb . SheetNames . forEach ( function ( y ) { assert ( wb . Sheets [ y ] , 'bad sheet ' + y ) ; } ) ;
} ) ;
it ( 'should have the right sheet names' , fs . existsSync ( sname ) ? function ( ) {
2014-05-30 01:09:20 +00:00
var file = fs . readFileSync ( sname , 'utf-8' ) . replace ( /\r/g , "" ) ;
2014-01-23 06:20:19 +00:00
var names = wb . SheetNames . map ( fixsheetname ) . join ( "\n" ) + "\n" ;
2013-12-27 03:15:16 +00:00
assert . equal ( names , file ) ;
2013-10-30 19:26:07 +00:00
} : null ) ;
} ) ;
2014-05-16 00:33:34 +00:00
describe ( x + ext + ' should generate CSV' , function ( ) {
2014-01-23 06:20:19 +00:00
wb . SheetNames . forEach ( function ( ws , i ) {
it ( '#' + i + ' (' + ws + ')' , function ( ) {
2014-05-03 18:51:10 +00:00
X . utils . make _csv ( wb . Sheets [ ws ] ) ;
2014-01-23 06:20:19 +00:00
} ) ;
} ) ;
} ) ;
2014-05-16 00:33:34 +00:00
describe ( x + ext + ' should generate JSON' , function ( ) {
2014-01-23 15:55:07 +00:00
wb . SheetNames . forEach ( function ( ws , i ) {
it ( '#' + i + ' (' + ws + ')' , function ( ) {
2014-05-03 18:51:10 +00:00
X . utils . sheet _to _row _object _array ( wb . Sheets [ ws ] ) ;
2014-01-23 15:55:07 +00:00
} ) ;
} ) ;
} ) ;
2014-05-16 00:33:34 +00:00
describe ( x + ext + ' should generate formulae' , function ( ) {
2014-01-23 15:55:07 +00:00
wb . SheetNames . forEach ( function ( ws , i ) {
it ( '#' + i + ' (' + ws + ')' , function ( ) {
2014-05-03 18:51:10 +00:00
X . utils . get _formulae ( wb . Sheets [ ws ] ) ;
2014-01-23 15:55:07 +00:00
} ) ;
} ) ;
} ) ;
2014-04-15 09:04:03 +00:00
if ( ! full ) return ;
2014-05-03 18:51:10 +00:00
var getfile = function ( dir , x , i , type ) {
var name = ( dir + x + '.' + i + type ) ;
2014-10-10 02:22:38 +00:00
if ( x . substr ( - 5 ) === ".xlsb" ) {
root = x . slice ( 0 , - 5 ) ;
2014-05-03 18:51:10 +00:00
if ( ! fs . existsSync ( name ) ) name = ( dir + root + '.xlsx.' + i + type ) ;
if ( ! fs . existsSync ( name ) ) name = ( dir + root + '.xlsm.' + i + type ) ;
if ( ! fs . existsSync ( name ) ) name = ( dir + root + '.xls.' + i + type ) ;
}
return name ;
} ;
2014-05-16 00:33:34 +00:00
describe ( x + ext + ' should generate correct CSV output' , function ( ) {
2013-10-30 19:26:07 +00:00
wb . SheetNames . forEach ( function ( ws , i ) {
2014-05-03 18:51:10 +00:00
var name = getfile ( dir , x , i , ".csv" ) ;
2013-10-30 19:26:07 +00:00
it ( '#' + i + ' (' + ws + ')' , fs . existsSync ( name ) ? function ( ) {
var file = fs . readFileSync ( name , 'utf-8' ) ;
2014-03-29 22:53:15 +00:00
var csv = X . utils . make _csv ( wb . Sheets [ ws ] ) ;
2014-05-03 18:51:10 +00:00
assert . equal ( fixcsv ( csv ) , fixcsv ( file ) , "CSV badness" ) ;
2013-10-30 19:26:07 +00:00
} : null ) ;
} ) ;
} ) ;
2014-05-16 00:33:34 +00:00
describe ( x + ext + ' should generate correct JSON output' , function ( ) {
2014-05-03 18:51:10 +00:00
wb . SheetNames . forEach ( function ( ws , i ) {
var rawjson = getfile ( dir , x , i , ".rawjson" ) ;
if ( fs . existsSync ( rawjson ) ) it ( '#' + i + ' (' + ws + ')' , function ( ) {
var file = fs . readFileSync ( rawjson , 'utf-8' ) ;
var json = X . utils . make _json ( wb . Sheets [ ws ] , { raw : true } ) ;
assert . equal ( JSON . stringify ( json ) , fixjson ( file ) , "JSON badness" ) ;
} ) ;
var jsonf = getfile ( dir , x , i , ".json" ) ;
if ( fs . existsSync ( jsonf ) ) it ( '#' + i + ' (' + ws + ')' , function ( ) {
var file = fs . readFileSync ( jsonf , 'utf-8' ) ;
var json = X . utils . make _json ( wb . Sheets [ ws ] ) ;
assert . equal ( JSON . stringify ( json ) , fixjson ( file ) , "JSON badness" ) ;
} ) ;
} ) ;
} ) ;
2014-05-22 20:15:47 +00:00
if ( fs . existsSync ( dir + '2013/' + x + '.xlsb' ) )
2014-05-16 00:33:34 +00:00
describe ( x + ext + '.xlsb from 2013' , function ( ) {
2014-02-17 08:44:22 +00:00
it ( 'should parse' , function ( ) {
2014-03-29 22:53:15 +00:00
var wb = X . readFile ( dir + '2013/' + x + '.xlsb' , opts ) ;
2014-02-17 08:44:22 +00:00
} ) ;
} ) ;
2013-10-30 19:26:07 +00:00
}
2014-05-29 22:30:03 +00:00
var wbtable = { } ;
2013-10-30 19:26:07 +00:00
describe ( 'should parse test files' , function ( ) {
files . forEach ( function ( x ) {
2014-05-16 00:50:55 +00:00
if ( ! fs . existsSync ( dir + x ) ) return ;
2013-10-30 19:26:07 +00:00
it ( x , x . substr ( - 8 ) == ".pending" ? null : function ( ) {
2014-03-29 22:53:15 +00:00
var wb = X . readFile ( dir + x , opts ) ;
2014-05-29 22:30:03 +00:00
wbtable [ dir + x ] = wb ;
2014-04-03 22:51:54 +00:00
parsetest ( x , wb , true ) ;
2014-05-29 22:30:03 +00:00
} ) ;
fullex . forEach ( function ( ext , idx ) {
it ( x + ' [' + ext + ']' , function ( ) {
var wb = wbtable [ dir + x ] ;
if ( ! wb ) wb = X . readFile ( dir + x , opts ) ;
2014-07-28 13:22:32 +00:00
parsetest ( x , X . read ( X . write ( wb , { type : "buffer" , bookType : ext . replace ( /\./ , "" ) } ) , { WTF : opts . WTF } ) , ext . replace ( /\./ , "" ) !== "xlsb" , ext ) ;
2014-05-16 00:33:34 +00:00
} ) ;
2014-04-03 22:51:54 +00:00
} ) ;
} ) ;
2014-04-15 09:04:03 +00:00
fileA . forEach ( function ( x ) {
2014-05-16 00:50:55 +00:00
if ( ! fs . existsSync ( dir + x ) ) return ;
2014-04-03 22:51:54 +00:00
it ( x , x . substr ( - 8 ) == ".pending" ? null : function ( ) {
var wb = X . readFile ( dir + x , { WTF : opts . wtf , sheetRows : 10 } ) ;
parsetest ( x , wb , false ) ;
2013-10-30 19:26:07 +00:00
} ) ;
} ) ;
} ) ;
2014-01-15 07:26:00 +00:00
2014-05-16 00:33:34 +00:00
describe ( 'parse options' , function ( ) {
2014-02-12 06:09:42 +00:00
var html _cell _types = [ 's' ] ;
before ( function ( ) {
2014-06-29 18:29:45 +00:00
X = require ( modp ) ;
2014-02-12 06:09:42 +00:00
} ) ;
2014-02-15 05:08:18 +00:00
describe ( 'cell' , function ( ) {
it ( 'should generate HTML by default' , function ( ) {
2014-03-29 22:53:15 +00:00
var wb = X . readFile ( paths . cst1 ) ;
2014-02-15 05:08:18 +00:00
var ws = wb . Sheets . Sheet1 ;
2014-02-13 06:22:42 +00:00
Object . keys ( ws ) . forEach ( function ( addr ) {
if ( addr [ 0 ] === "!" || ! ws . hasOwnProperty ( addr ) ) return ;
2014-02-15 05:08:18 +00:00
assert ( html _cell _types . indexOf ( ws [ addr ] . t ) === - 1 || ws [ addr ] . h ) ;
2014-02-13 06:22:42 +00:00
} ) ;
} ) ;
2014-02-15 05:08:18 +00:00
it ( 'should not generate HTML when requested' , function ( ) {
2014-03-29 22:53:15 +00:00
var wb = X . readFile ( paths . cst1 , { cellHTML : false } ) ;
2014-02-15 05:08:18 +00:00
var ws = wb . Sheets . Sheet1 ;
2014-02-13 06:22:42 +00:00
Object . keys ( ws ) . forEach ( function ( addr ) {
if ( addr [ 0 ] === "!" || ! ws . hasOwnProperty ( addr ) ) return ;
2014-02-15 05:08:18 +00:00
assert ( typeof ws [ addr ] . h === 'undefined' ) ;
2014-02-13 06:22:42 +00:00
} ) ;
} ) ;
2014-02-15 05:08:18 +00:00
it ( 'should generate formulae by default' , function ( ) {
2014-03-29 22:53:15 +00:00
var wb = X . readFile ( paths . fstb ) ;
2014-02-15 05:08:18 +00:00
var found = false ;
wb . SheetNames . forEach ( function ( s ) {
var ws = wb . Sheets [ s ] ;
Object . keys ( ws ) . forEach ( function ( addr ) {
if ( addr [ 0 ] === "!" || ! ws . hasOwnProperty ( addr ) ) return ;
if ( typeof ws [ addr ] . f !== 'undefined' ) return found = true ;
} ) ;
2014-02-13 08:48:41 +00:00
} ) ;
2014-02-15 05:08:18 +00:00
assert ( found ) ;
2014-02-13 08:48:41 +00:00
} ) ;
2014-02-15 05:08:18 +00:00
it ( 'should not generate formulae when requested' , function ( ) {
2014-03-29 22:53:15 +00:00
var wb = X . readFile ( paths . fstb , { cellFormula : false } ) ;
2014-02-15 05:08:18 +00:00
wb . SheetNames . forEach ( function ( s ) {
var ws = wb . Sheets [ s ] ;
Object . keys ( ws ) . forEach ( function ( addr ) {
if ( addr [ 0 ] === "!" || ! ws . hasOwnProperty ( addr ) ) return ;
assert ( typeof ws [ addr ] . f === 'undefined' ) ;
} ) ;
} ) ;
} ) ;
it ( 'should not generate number formats by default' , function ( ) {
2014-03-29 22:53:15 +00:00
var wb = X . readFile ( paths . nf1 ) ;
2014-02-15 05:08:18 +00:00
wb . SheetNames . forEach ( function ( s ) {
var ws = wb . Sheets [ s ] ;
Object . keys ( ws ) . forEach ( function ( addr ) {
if ( addr [ 0 ] === "!" || ! ws . hasOwnProperty ( addr ) ) return ;
assert ( typeof ws [ addr ] . z === 'undefined' ) ;
} ) ;
2014-02-13 08:48:41 +00:00
} ) ;
} ) ;
2014-02-15 05:08:18 +00:00
it ( 'should generate number formats when requested' , function ( ) {
2014-03-29 22:53:15 +00:00
var wb = X . readFile ( paths . nf1 , { cellNF : true } ) ;
2014-02-15 05:08:18 +00:00
wb . SheetNames . forEach ( function ( s ) {
var ws = wb . Sheets [ s ] ;
Object . keys ( ws ) . forEach ( function ( addr ) {
if ( addr [ 0 ] === "!" || ! ws . hasOwnProperty ( addr ) ) return ;
2014-02-26 19:30:32 +00:00
assert ( ws [ addr ] . t !== 'n' || typeof ws [ addr ] . z !== 'undefined' ) ;
2014-02-15 05:08:18 +00:00
} ) ;
} ) ;
} ) ;
2014-05-29 22:30:03 +00:00
it ( 'should not generate cell styles by default' , function ( ) {
var wb = X . readFile ( paths . css1 ) ;
wb . SheetNames . forEach ( function ( s ) {
var ws = wb . Sheets [ s ] ;
Object . keys ( ws ) . forEach ( function ( addr ) {
if ( addr [ 0 ] === "!" || ! ws . hasOwnProperty ( addr ) ) return ;
assert ( typeof ws [ addr ] . s === 'undefined' ) ;
} ) ;
} ) ;
} ) ;
it ( 'XLSX should generate cell styles when requested' , function ( ) {
var wb = X . readFile ( paths . css1 , { cellStyles : true } ) ;
var found = false ;
wb . SheetNames . forEach ( function ( s ) {
var ws = wb . Sheets [ s ] ;
Object . keys ( ws ) . forEach ( function ( addr ) {
if ( addr [ 0 ] === "!" || ! ws . hasOwnProperty ( addr ) ) return ;
if ( typeof ws [ addr ] . s !== 'undefined' ) return found = true ;
} ) ;
} ) ;
assert ( found ) ;
} ) ;
2014-10-26 05:26:18 +00:00
it ( 'should not generate cell dates by default' , function ( ) {
var wb = X . readFile ( paths . dt1 ) ;
wb . SheetNames . forEach ( function ( s ) {
var ws = wb . Sheets [ s ] ;
Object . keys ( ws ) . forEach ( function ( addr ) {
if ( addr [ 0 ] === "!" || ! ws . hasOwnProperty ( addr ) ) return ;
assert ( ws [ addr ] . t !== 'd' ) ;
} ) ;
} ) ;
} ) ;
it ( 'XLSB should not generate cell dates' , function ( ) {
var wb = X . readFile ( paths . dt2 , { cellDates : true } ) ;
wb . SheetNames . forEach ( function ( s ) {
var ws = wb . Sheets [ s ] ;
Object . keys ( ws ) . forEach ( function ( addr ) {
if ( addr [ 0 ] === "!" || ! ws . hasOwnProperty ( addr ) ) return ;
assert ( ws [ addr ] . t !== 'd' ) ;
} ) ;
} ) ;
} ) ;
it ( 'XLSX should generate cell dates when requested' , function ( ) {
var wb = X . readFile ( paths . dt1 , { cellDates : true } ) ;
var found = false ;
wb . SheetNames . forEach ( function ( s ) {
var ws = wb . Sheets [ s ] ;
Object . keys ( ws ) . forEach ( function ( addr ) {
if ( addr [ 0 ] === "!" || ! ws . hasOwnProperty ( addr ) ) return ;
if ( ws [ addr ] . t === 'd' ) return found = true ;
} ) ;
} ) ;
assert ( found ) ;
} ) ;
2014-02-15 05:08:18 +00:00
} ) ;
describe ( 'sheet' , function ( ) {
it ( 'should not generate sheet stubs by default' , function ( ) {
2014-03-29 22:53:15 +00:00
var wb = X . readFile ( paths . mc1 ) ;
2014-02-15 05:08:18 +00:00
assert . throws ( function ( ) { wb . Sheets . Merge . A2 . v ; } ) ;
2014-03-29 22:53:15 +00:00
wb = X . readFile ( paths . mc2 ) ;
2014-03-29 02:05:50 +00:00
assert . throws ( function ( ) { wb . Sheets . Merge . A2 . v ; } ) ;
2014-10-26 05:26:18 +00:00
wb = X . readFile ( paths . mc3 ) ;
assert . throws ( function ( ) { wb . Sheets . Merge . A2 . v ; } ) ;
2014-02-15 05:08:18 +00:00
} ) ;
it ( 'should generate sheet stubs when requested' , function ( ) {
2014-03-29 22:53:15 +00:00
var wb = X . readFile ( paths . mc1 , { sheetStubs : true } ) ;
assert ( typeof wb . Sheets . Merge . A2 . t !== 'undefined' ) ;
wb = X . readFile ( paths . mc2 , { sheetStubs : true } ) ;
2014-02-15 05:08:18 +00:00
assert ( typeof wb . Sheets . Merge . A2 . t !== 'undefined' ) ;
2014-10-26 05:26:18 +00:00
/* TODO: ODS */
2014-02-15 05:08:18 +00:00
} ) ;
2014-03-29 02:05:50 +00:00
function checkcells ( wb , A46 , B26 , C16 , D2 ) {
assert ( ( typeof wb . Sheets . Text . A46 !== 'undefined' ) == A46 ) ;
assert ( ( typeof wb . Sheets . Text . B26 !== 'undefined' ) == B26 ) ;
assert ( ( typeof wb . Sheets . Text . C16 !== 'undefined' ) == C16 ) ;
assert ( ( typeof wb . Sheets . Text . D2 !== 'undefined' ) == D2 ) ;
}
2014-02-19 03:03:28 +00:00
it ( 'should read all cells by default' , function ( ) {
2014-03-29 22:53:15 +00:00
var wb = X . readFile ( paths . fst1 ) ;
2014-03-29 02:05:50 +00:00
checkcells ( wb , true , true , true , true ) ;
2014-03-29 22:53:15 +00:00
wb = X . readFile ( paths . fst2 ) ;
2014-03-29 02:05:50 +00:00
checkcells ( wb , true , true , true , true ) ;
2014-10-26 05:26:18 +00:00
wb = X . readFile ( paths . fst3 ) ;
checkcells ( wb , true , true , true , true ) ;
2014-02-19 03:03:28 +00:00
} ) ;
it ( 'sheetRows n=20' , function ( ) {
2014-03-29 22:53:15 +00:00
var wb = X . readFile ( paths . fst1 , { sheetRows : 20 } ) ;
2014-03-29 02:05:50 +00:00
checkcells ( wb , false , false , true , true ) ;
2014-03-29 22:53:15 +00:00
wb = X . readFile ( paths . fst2 , { sheetRows : 20 } ) ;
2014-03-29 02:05:50 +00:00
checkcells ( wb , false , false , true , true ) ;
2014-10-26 05:26:18 +00:00
wb = X . readFile ( paths . fst3 , { sheetRows : 20 } ) ;
checkcells ( wb , false , false , true , true ) ;
2014-02-19 03:03:28 +00:00
} ) ;
it ( 'sheetRows n=10' , function ( ) {
2014-03-29 22:53:15 +00:00
var wb = X . readFile ( paths . fst1 , { sheetRows : 10 } ) ;
2014-03-29 02:05:50 +00:00
checkcells ( wb , false , false , false , true ) ;
2014-03-29 22:53:15 +00:00
wb = X . readFile ( paths . fst2 , { sheetRows : 10 } ) ;
2014-03-29 02:05:50 +00:00
checkcells ( wb , false , false , false , true ) ;
2014-10-26 05:26:18 +00:00
wb = X . readFile ( paths . fst3 , { sheetRows : 10 } ) ;
checkcells ( wb , false , false , false , true ) ;
2014-02-19 03:03:28 +00:00
} ) ;
2014-02-13 08:48:41 +00:00
} ) ;
2014-02-14 06:25:46 +00:00
describe ( 'book' , function ( ) {
it ( 'bookSheets should not generate sheets' , function ( ) {
2014-03-29 22:53:15 +00:00
var wb = X . readFile ( paths . mc1 , { bookSheets : true } ) ;
assert ( typeof wb . Sheets === 'undefined' ) ;
var wb = X . readFile ( paths . mc2 , { bookSheets : true } ) ;
2014-02-14 06:25:46 +00:00
assert ( typeof wb . Sheets === 'undefined' ) ;
} ) ;
it ( 'bookProps should not generate sheets' , function ( ) {
2014-03-29 22:53:15 +00:00
var wb = X . readFile ( paths . nf1 , { bookProps : true } ) ;
assert ( typeof wb . Sheets === 'undefined' ) ;
wb = X . readFile ( paths . nf2 , { bookProps : true } ) ;
2014-02-14 06:25:46 +00:00
assert ( typeof wb . Sheets === 'undefined' ) ;
} ) ;
it ( 'bookProps && bookSheets should not generate sheets' , function ( ) {
2014-03-29 22:53:15 +00:00
var wb = X . readFile ( paths . lon1 , { bookProps : true , bookSheets : true } ) ;
2014-02-14 06:25:46 +00:00
assert ( typeof wb . Sheets === 'undefined' ) ;
} ) ;
2014-02-15 05:08:18 +00:00
it ( 'should not generate deps by default' , function ( ) {
2014-03-29 22:53:15 +00:00
var wb = X . readFile ( paths . fst1 ) ;
assert ( typeof wb . Deps === 'undefined' || ! ( wb . Deps . length > 0 ) ) ;
wb = X . readFile ( paths . fst2 ) ;
2014-02-17 08:44:22 +00:00
assert ( typeof wb . Deps === 'undefined' || ! ( wb . Deps . length > 0 ) ) ;
} ) ;
it ( 'bookDeps should generate deps' , function ( ) {
2014-03-29 22:53:15 +00:00
var wb = X . readFile ( paths . fst1 , { bookDeps : true } ) ;
assert ( typeof wb . Deps !== 'undefined' && wb . Deps . length > 0 ) ;
wb = X . readFile ( paths . fst2 , { bookDeps : true } ) ;
2014-02-15 05:08:18 +00:00
assert ( typeof wb . Deps !== 'undefined' && wb . Deps . length > 0 ) ;
} ) ;
2014-03-29 22:53:15 +00:00
var ckf = function ( wb , fields , exists ) { fields . forEach ( function ( f ) {
assert ( ( typeof wb [ f ] !== 'undefined' ) == exists ) ;
} ) ; } ;
it ( 'should not generate book files by default' , function ( ) {
var wb = X . readFile ( paths . fst1 ) ;
ckf ( wb , [ 'files' , 'keys' ] , false ) ;
wb = X . readFile ( paths . fst2 ) ;
ckf ( wb , [ 'files' , 'keys' ] , false ) ;
} ) ;
it ( 'bookFiles should generate book files' , function ( ) {
var wb = X . readFile ( paths . fst1 , { bookFiles : true } ) ;
ckf ( wb , [ 'files' , 'keys' ] , true ) ;
wb = X . readFile ( paths . fst2 , { bookFiles : true } ) ;
ckf ( wb , [ 'files' , 'keys' ] , true ) ;
2014-02-15 05:08:18 +00:00
} ) ;
2014-04-03 22:51:54 +00:00
it ( 'should not generate VBA by default' , function ( ) {
var wb = X . readFile ( paths . nf1 ) ;
assert ( typeof wb . vbaraw === 'undefined' ) ;
wb = X . readFile ( paths . nf2 ) ;
assert ( typeof wb . vbaraw === 'undefined' ) ;
} ) ;
it ( 'bookVBA should generate vbaraw' , function ( ) {
var wb = X . readFile ( paths . nf1 , { bookVBA : true } ) ;
assert ( typeof wb . vbaraw !== 'undefined' ) ;
wb = X . readFile ( paths . nf2 , { bookVBA : true } ) ;
assert ( typeof wb . vbaraw !== 'undefined' ) ;
} ) ;
2014-02-14 06:25:46 +00:00
} ) ;
} ) ;
describe ( 'input formats' , function ( ) {
it ( 'should read binary strings' , function ( ) {
2014-03-29 22:53:15 +00:00
X . read ( fs . readFileSync ( paths . cst1 , 'binary' ) , { type : 'binary' } ) ;
X . read ( fs . readFileSync ( paths . cst2 , 'binary' ) , { type : 'binary' } ) ;
2014-02-14 06:25:46 +00:00
} ) ;
it ( 'should read base64 strings' , function ( ) {
2014-03-29 22:53:15 +00:00
X . read ( fs . readFileSync ( paths . cst1 , 'base64' ) , { type : 'base64' } ) ;
X . read ( fs . readFileSync ( paths . cst2 , 'base64' ) , { type : 'base64' } ) ;
2014-02-14 06:25:46 +00:00
} ) ;
2014-05-16 00:33:34 +00:00
it ( 'should read buffers' , function ( ) {
X . read ( fs . readFileSync ( paths . cst1 ) , { type : 'buffer' } ) ;
X . read ( fs . readFileSync ( paths . cst2 ) , { type : 'buffer' } ) ;
} ) ;
it ( 'should throw if format is unknown' , function ( ) {
assert . throws ( function ( ) { X . read ( fs . readFileSync ( paths . cst1 ) , { type : 'dafuq' } ) ; } ) ;
assert . throws ( function ( ) { X . read ( fs . readFileSync ( paths . cst2 ) , { type : 'dafuq' } ) ; } ) ;
} ) ;
it ( 'should infer buffer type' , function ( ) {
X . read ( fs . readFileSync ( paths . cst1 ) ) ;
X . read ( fs . readFileSync ( paths . cst2 ) ) ;
} ) ;
it ( 'should default to base64 type' , function ( ) {
assert . throws ( function ( ) { X . read ( fs . readFileSync ( paths . cst1 , 'binary' ) ) ; } ) ;
assert . throws ( function ( ) { X . read ( fs . readFileSync ( paths . cst2 , 'binary' ) ) ; } ) ;
X . read ( fs . readFileSync ( paths . cst1 , 'base64' ) ) ;
X . read ( fs . readFileSync ( paths . cst2 , 'base64' ) ) ;
} ) ;
} ) ;
describe ( 'output formats' , function ( ) {
var wb1 , wb2 ;
before ( function ( ) {
2014-10-26 05:26:18 +00:00
X = require ( modp ) ;
2014-05-16 00:33:34 +00:00
wb1 = X . readFile ( paths . cp1 ) ;
wb2 = X . readFile ( paths . cp2 ) ;
} ) ;
it ( 'should write binary strings' , function ( ) {
X . write ( wb1 , { type : 'binary' } ) ;
X . write ( wb2 , { type : 'binary' } ) ;
X . read ( X . write ( wb1 , { type : 'binary' } ) , { type : 'binary' } ) ;
X . read ( X . write ( wb2 , { type : 'binary' } ) , { type : 'binary' } ) ;
} ) ;
it ( 'should write base64 strings' , function ( ) {
X . write ( wb1 , { type : 'base64' } ) ;
X . write ( wb2 , { type : 'base64' } ) ;
X . read ( X . write ( wb1 , { type : 'base64' } ) , { type : 'base64' } ) ;
X . read ( X . write ( wb2 , { type : 'base64' } ) , { type : 'base64' } ) ;
} ) ;
it ( 'should write buffers' , function ( ) {
X . write ( wb1 , { type : 'buffer' } ) ;
X . write ( wb2 , { type : 'buffer' } ) ;
X . read ( X . write ( wb1 , { type : 'buffer' } ) , { type : 'buffer' } ) ;
X . read ( X . write ( wb2 , { type : 'buffer' } ) , { type : 'buffer' } ) ;
} ) ;
it ( 'should throw if format is unknown' , function ( ) {
assert . throws ( function ( ) { X . write ( wb1 , { type : 'dafuq' } ) ; } ) ;
assert . throws ( function ( ) { X . write ( wb2 , { type : 'dafuq' } ) ; } ) ;
} ) ;
2014-02-12 06:09:42 +00:00
} ) ;
2014-02-14 03:39:03 +00:00
2014-05-16 00:33:34 +00:00
function coreprop ( wb ) {
assert . equal ( wb . Props . Title , 'Example with properties' ) ;
assert . equal ( wb . Props . Subject , 'Test it before you code it' ) ;
assert . equal ( wb . Props . Author , 'Pony Foo' ) ;
assert . equal ( wb . Props . Manager , 'Despicable Drew' ) ;
assert . equal ( wb . Props . Company , 'Vector Inc' ) ;
assert . equal ( wb . Props . Category , 'Quirky' ) ;
assert . equal ( wb . Props . Keywords , 'example humor' ) ;
assert . equal ( wb . Props . Comments , 'some comments' ) ;
assert . equal ( wb . Props . LastAuthor , 'Hugues' ) ;
}
function custprop ( wb ) {
assert . equal ( wb . Custprops [ 'I am a boolean' ] , true ) ;
assert . equal ( wb . Custprops [ 'Date completed' ] . toISOString ( ) , '1967-03-09T16:30:00.000Z' ) ;
assert . equal ( wb . Custprops . Status , 2 ) ;
assert . equal ( wb . Custprops . Counter , - 3.14 ) ;
}
2014-05-29 22:30:03 +00:00
function cmparr ( x ) { for ( var i = 1 ; i != x . length ; ++ i ) assert . deepEqual ( x [ 0 ] , x [ i ] ) ; }
function deepcmp ( x , y , k , m , c ) {
var s = k . indexOf ( "." ) ;
m = ( m || "" ) + "|" + ( s > - 1 ? k . substr ( 0 , s ) : k ) ;
if ( s < 0 ) return assert [ c < 0 ? 'notEqual' : 'equal' ] ( x [ k ] , y [ k ] , m ) ;
return deepcmp ( x [ k . substr ( 0 , s ) ] , y [ k . substr ( 0 , s ) ] , k . substr ( s + 1 ) , m , c )
}
var styexc = [
'A2|H10|bgColor.rgb' ,
'F6|H1|patternType'
]
var stykeys = [
"patternType" ,
"fgColor.rgb" ,
"bgColor.rgb"
] ;
function diffsty ( ws , r1 , r2 ) {
var c1 = ws [ r1 ] . s , c2 = ws [ r2 ] . s ;
stykeys . forEach ( function ( m ) {
var c = - 1 ;
if ( styexc . indexOf ( r1 + "|" + r2 + "|" + m ) > - 1 ) c = 1 ;
else if ( styexc . indexOf ( r2 + "|" + r1 + "|" + m ) > - 1 ) c = 1 ;
deepcmp ( c1 , c2 , m , r1 + "," + r2 , c ) ;
} ) ;
}
2014-05-16 00:33:34 +00:00
describe ( 'parse features' , function ( ) {
2014-03-29 02:05:50 +00:00
it ( 'should have comment as part of cell properties' , function ( ) {
2014-06-29 18:29:45 +00:00
var X = require ( modp ) ;
2014-03-29 02:05:50 +00:00
var sheet = 'Sheet1' ;
2014-03-29 22:53:15 +00:00
var wb1 = X . readFile ( paths . swc1 ) ;
var wb2 = X . readFile ( paths . swc2 ) ;
2014-03-29 02:05:50 +00:00
2014-03-29 22:53:15 +00:00
[ wb1 , wb2 ] . map ( function ( wb ) { return wb . Sheets [ sheet ] ; } ) . forEach ( function ( ws , i ) {
2014-02-15 05:08:18 +00:00
assert . equal ( ws . B1 . c . length , 1 , "must have 1 comment" ) ;
assert . equal ( ws . B1 . c [ 0 ] . a , "Yegor Kozlov" , "must have the same author" ) ;
2014-04-23 01:37:08 +00:00
assert . equal ( ws . B1 . c [ 0 ] . t . replace ( /\r\n/g , "\n" ) . replace ( /\r/g , "\n" ) , "Yegor Kozlov:\nfirst cell" , "must have the concatenated texts" ) ;
2014-03-29 22:53:15 +00:00
if ( i > 0 ) return ;
2014-03-29 02:05:50 +00:00
assert . equal ( ws . B1 . c [ 0 ] . r , '<r><rPr><b/><sz val="8"/><color indexed="81"/><rFont val="Tahoma"/></rPr><t>Yegor Kozlov:</t></r><r><rPr><sz val="8"/><color indexed="81"/><rFont val="Tahoma"/></rPr><t xml:space="preserve">\r\nfirst cell</t></r>' , "must have the rich text representation" ) ;
assert . equal ( ws . B1 . c [ 0 ] . h , '<span style="font-weight: bold;">Yegor Kozlov:</span><span style=""><br/>first cell</span>' , "must have the html representation" ) ;
2014-02-15 05:08:18 +00:00
} ) ;
2014-02-14 03:39:03 +00:00
} ) ;
2014-02-15 03:15:10 +00:00
2014-02-19 03:03:28 +00:00
describe ( 'should parse core properties and custom properties' , function ( ) {
2014-03-29 22:53:15 +00:00
var wb1 , wb2 ;
2014-02-15 05:08:18 +00:00
before ( function ( ) {
2014-06-29 18:29:45 +00:00
X = require ( modp ) ;
2014-03-29 22:53:15 +00:00
wb1 = X . readFile ( paths . cp1 ) ;
wb2 = X . readFile ( paths . cp2 ) ;
2014-02-15 05:08:18 +00:00
} ) ;
2014-03-29 02:05:50 +00:00
2014-03-29 22:53:15 +00:00
it ( N1 + ' should parse core properties' , function ( ) { coreprop ( wb1 ) ; } ) ;
it ( N2 + ' should parse core properties' , function ( ) { coreprop ( wb2 ) ; } ) ;
it ( N1 + ' should parse custom properties' , function ( ) { custprop ( wb1 ) ; } ) ;
it ( N2 + ' should parse custom properties' , function ( ) { custprop ( wb2 ) ; } ) ;
2014-02-15 03:15:10 +00:00
} ) ;
2014-02-19 03:03:28 +00:00
describe ( 'sheetRows' , function ( ) {
it ( 'should use original range if not set' , function ( ) {
2014-03-29 02:05:50 +00:00
var opts = { } ;
2014-03-29 22:53:15 +00:00
var wb1 = X . readFile ( paths . fst1 , opts ) ;
var wb2 = X . readFile ( paths . fst2 , opts ) ;
[ wb1 , wb2 ] . forEach ( function ( wb ) {
2014-03-29 02:05:50 +00:00
assert . equal ( wb . Sheets . Text [ "!ref" ] , "A1:F49" ) ;
} ) ;
2014-02-19 03:03:28 +00:00
} ) ;
it ( 'should adjust range if set' , function ( ) {
2014-03-29 02:05:50 +00:00
var opts = { sheetRows : 10 } ;
2014-03-29 22:53:15 +00:00
var wb1 = X . readFile ( paths . fst1 , opts ) ;
var wb2 = X . readFile ( paths . fst2 , opts ) ;
[ wb1 , wb2 ] . forEach ( function ( wb ) {
2014-03-29 02:05:50 +00:00
assert . equal ( wb . Sheets . Text [ "!fullref" ] , "A1:F49" ) ;
assert . equal ( wb . Sheets . Text [ "!ref" ] , "A1:F10" ) ;
} ) ;
2014-02-19 03:03:28 +00:00
} ) ;
it ( 'should not generate comment cells' , function ( ) {
2014-03-29 02:05:50 +00:00
var opts = { sheetRows : 10 } ;
2014-03-29 22:53:15 +00:00
var wb1 = X . readFile ( paths . cst1 , opts ) ;
var wb2 = X . readFile ( paths . cst2 , opts ) ;
[ wb1 , wb2 ] . forEach ( function ( wb ) {
2014-03-29 02:05:50 +00:00
assert . equal ( wb . Sheets . Sheet7 [ "!fullref" ] , "A1:N34" ) ;
2014-05-03 18:51:10 +00:00
assert . equal ( wb . Sheets . Sheet7 [ "!ref" ] , "A1" ) ;
2014-03-29 02:05:50 +00:00
} ) ;
2014-02-19 03:03:28 +00:00
} ) ;
} ) ;
2014-03-23 21:30:00 +00:00
describe ( 'merge cells' , function ( ) {
2014-03-29 22:53:15 +00:00
var wb1 , wb2 ;
2014-03-23 21:30:00 +00:00
before ( function ( ) {
2014-06-29 18:29:45 +00:00
X = require ( modp ) ;
2014-03-29 22:53:15 +00:00
wb1 = X . readFile ( paths . mc1 ) ;
wb2 = X . readFile ( paths . mc2 ) ;
2014-10-26 05:26:18 +00:00
wb3 = X . readFile ( paths . mc3 ) ;
2014-03-23 21:30:00 +00:00
} ) ;
it ( 'should have !merges' , function ( ) {
2014-03-29 22:53:15 +00:00
assert ( wb1 . Sheets . Merge [ '!merges' ] ) ;
assert ( wb2 . Sheets . Merge [ '!merges' ] ) ;
2014-10-26 05:26:18 +00:00
assert ( wb3 . Sheets . Merge [ '!merges' ] ) ;
var m = [ wb1 , wb2 , wb3 ] . map ( function ( x ) { return x . Sheets . Merge [ '!merges' ] . map ( function ( y ) { return X . utils . encode _range ( y ) ; } ) ; } ) ;
2014-03-23 21:30:00 +00:00
assert . deepEqual ( m [ 0 ] . sort ( ) , m [ 1 ] . sort ( ) ) ;
2014-10-26 05:26:18 +00:00
assert . deepEqual ( m [ 0 ] . sort ( ) , m [ 2 ] . sort ( ) ) ;
2014-03-23 21:30:00 +00:00
} ) ;
} ) ;
2014-03-29 22:53:15 +00:00
2014-04-15 09:04:03 +00:00
describe ( 'should find hyperlinks' , function ( ) {
var wb1 , wb2 ;
before ( function ( ) {
2014-06-29 18:29:45 +00:00
X = require ( modp ) ;
2014-04-15 09:04:03 +00:00
wb1 = X . readFile ( paths . hl1 ) ;
wb2 = X . readFile ( paths . hl2 ) ;
} ) ;
function hlink ( wb ) {
var ws = wb . Sheets . Sheet1 ;
assert . equal ( ws . A1 . l . Target , "http://www.sheetjs.com" ) ;
assert . equal ( ws . A2 . l . Target , "http://oss.sheetjs.com" ) ;
assert . equal ( ws . A3 . l . Target , "http://oss.sheetjs.com#foo" ) ;
assert . equal ( ws . A4 . l . Target , "mailto:dev@sheetjs.com" ) ;
assert . equal ( ws . A5 . l . Target , "mailto:dev@sheetjs.com?subject=hyperlink" ) ;
assert . equal ( ws . A6 . l . Target , "../../sheetjs/Documents/Test.xlsx" ) ;
assert . equal ( ws . A7 . l . Target , "http://sheetjs.com" ) ;
}
it ( N1 , function ( ) { hlink ( wb1 ) ; } ) ;
it ( N2 , function ( ) { hlink ( wb2 ) ; } ) ;
} ) ;
2014-03-29 22:53:15 +00:00
describe ( 'should parse cells with date type (XLSX/XLSM)' , function ( ) {
2014-10-26 05:26:18 +00:00
it ( 'Must have read the date' , function ( ) {
var wb , ws ;
X = require ( modp ) ;
wb = X . readFile ( paths . dt1 ) ;
2014-03-29 22:53:15 +00:00
var sheetName = 'Sheet1' ;
ws = wb . Sheets [ sheetName ] ;
var sheet = X . utils . sheet _to _row _object _array ( ws ) ;
assert . equal ( sheet [ 3 ] [ 'てすと' ] , '2/14/14' ) ;
} ) ;
2014-10-26 05:26:18 +00:00
it ( 'cellDates should not affect formatted text' , function ( ) {
var wb1 , ws1 , wb2 , ws2 ;
var sheetName = 'Sheet1' ;
X = require ( modp ) ;
wb1 = X . readFile ( paths . dt1 ) ;
ws1 = wb1 . Sheets [ sheetName ] ;
wb2 = X . readFile ( paths . dt2 ) ;
ws2 = wb2 . Sheets [ sheetName ] ;
assert . equal ( X . utils . sheet _to _csv ( ws1 ) , X . utils . sheet _to _csv ( ws2 ) ) ;
} ) ;
2014-03-29 22:53:15 +00:00
} ) ;
2014-05-29 22:30:03 +00:00
describe ( 'should correctly handle styles' , function ( ) {
var ws , rn , rn2 ;
before ( function ( ) {
2014-06-02 05:19:07 +00:00
ws = X . readFile ( paths . css1 , { cellStyles : true , WTF : 1 } ) . Sheets . Sheet1 ;
2014-05-29 22:30:03 +00:00
rn = function ( range ) {
var r = X . utils . decode _range ( range ) ;
var out = [ ] ;
for ( var R = r . s . r ; R <= r . e . r ; ++ R ) for ( var C = r . s . c ; C <= r . e . c ; ++ C )
out . push ( X . utils . encode _cell ( { c : C , r : R } ) ) ;
return out ;
} ;
rn2 = function ( r ) { return [ ] . concat . apply ( [ ] , r . split ( "," ) . map ( rn ) ) ; } ;
} ) ;
var ranges = [
'A1:D1,F1:G1' , 'A2:D2,F2:G2' , /* rows */
'A3:A10' , 'B3:B10' , 'E1:E10' , 'F6:F8' , /* cols */
'H1:J4' , 'H10' /* blocks */
2014-06-02 05:19:07 +00:00
] ;
var exp = [
{ patternType : 'darkHorizontal' ,
fgColor : { theme : 9 , raw _rgb : 'F79646' } ,
bgColor : { theme : 5 , raw _rgb : 'C0504D' } } ,
{ patternType : 'darkUp' ,
fgColor : { theme : 3 , raw _rgb : 'EEECE1' } ,
bgColor : { theme : 7 , raw _rgb : '8064A2' } } ,
{ patternType : 'darkGray' ,
fgColor : { theme : 3 , raw _rgb : 'EEECE1' } ,
bgColor : { theme : 1 , raw _rgb : 'FFFFFF' } } ,
{ patternType : 'lightGray' ,
fgColor : { theme : 6 , raw _rgb : '9BBB59' } ,
bgColor : { theme : 2 , raw _rgb : '1F497D' } } ,
{ patternType : 'lightDown' ,
fgColor : { theme : 4 , raw _rgb : '4F81BD' } ,
bgColor : { theme : 7 , raw _rgb : '8064A2' } } ,
{ patternType : 'lightGrid' ,
fgColor : { theme : 6 , raw _rgb : '9BBB59' } ,
bgColor : { theme : 9 , raw _rgb : 'F79646' } } ,
{ patternType : 'lightGrid' ,
fgColor : { theme : 4 , raw _rgb : '4F81BD' } ,
bgColor : { theme : 2 , raw _rgb : '1F497D' } } ,
{ patternType : 'lightVertical' ,
fgColor : { theme : 3 , raw _rgb : 'EEECE1' } ,
bgColor : { theme : 7 , raw _rgb : '8064A2' } }
] ;
2014-05-29 22:30:03 +00:00
ranges . forEach ( function ( rng ) {
it ( rng , function ( ) { cmparr ( rn2 ( rng ) . map ( function ( x ) { return ws [ x ] . s ; } ) ) ; } ) ;
} ) ;
it ( 'different styles' , function ( ) {
for ( var i = 0 ; i != ranges . length - 1 ; ++ i ) {
for ( var j = i + 1 ; j != ranges . length ; ++ j ) {
diffsty ( ws , rn2 ( ranges [ i ] ) [ 0 ] , rn2 ( ranges [ j ] ) [ 0 ] ) ;
}
}
} ) ;
2014-06-02 05:19:07 +00:00
it ( 'correct styles' , function ( ) {
var styles = ranges . map ( function ( r ) { return rn2 ( r ) [ 0 ] } ) . map ( function ( r ) { return ws [ r ] . s } ) ;
for ( var i = 0 ; i != exp . length ; ++ i ) {
[
"fgColor.theme" , "fgColor.raw_rgb" ,
"bgColor.theme" , "bgColor.raw_rgb" ,
"patternType"
] . forEach ( function ( k ) { deepcmp ( exp [ i ] , styles [ i ] , k , i + ":" + k ) ; } ) ;
}
} ) ;
2014-05-29 22:30:03 +00:00
} ) ;
2014-02-15 03:15:10 +00:00
} ) ;
2014-03-29 02:05:50 +00:00
2014-10-26 05:26:18 +00:00
function seq ( end , start ) {
var s = start || 0 ;
var o = new Array ( end - s ) ;
for ( var i = 0 ; i != o . length ; ++ i ) o [ i ] = s + i ;
return o ;
}
2014-05-16 00:33:34 +00:00
describe ( 'roundtrip features' , function ( ) {
before ( function ( ) {
2014-06-29 18:29:45 +00:00
X = require ( modp ) ;
2014-03-29 02:05:50 +00:00
} ) ;
2014-05-16 00:33:34 +00:00
describe ( 'should parse core properties and custom properties' , function ( ) {
var wb1 , wb2 , base = './tmp/cp' ;
before ( function ( ) {
wb1 = X . readFile ( paths . cp1 ) ;
wb2 = X . readFile ( paths . cp2 ) ;
fullex . forEach ( function ( p ) {
X . writeFile ( wb1 , base + '.xlsm' + p ) ;
X . writeFile ( wb2 , base + '.xlsb' + p ) ;
} ) ;
} ) ;
fullex . forEach ( function ( p ) { [ '.xlsm' , '.xlsb' ] . forEach ( function ( q ) {
it ( q + p + ' should roundtrip core and custom properties' , function ( ) {
var wb = X . readFile ( base + q + p ) ;
coreprop ( wb ) ;
custprop ( wb ) ;
} ) ; } ) ;
} ) ;
2014-03-29 02:05:50 +00:00
} ) ;
2014-08-26 17:40:04 +00:00
describe ( 'should preserve features' , function ( ) {
it ( 'merge cells' , function ( ) {
var wb1 = X . readFile ( paths . mc1 ) ;
var wb2 = X . read ( X . write ( wb1 , { type : 'binary' } ) , { type : 'binary' } ) ;
var m1 = wb1 . Sheets . Merge [ '!merges' ] . map ( X . utils . encode _range ) ;
var m2 = wb2 . Sheets . Merge [ '!merges' ] . map ( X . utils . encode _range ) ;
assert . equal ( m1 . length , m2 . length ) ;
for ( var i = 0 ; i < m1 . length ; ++ i ) assert . equal ( m1 [ i ] , m2 [ i ] ) ;
} ) ;
} ) ;
2014-10-26 05:26:18 +00:00
describe ( 'should preserve dates' , function ( ) {
seq ( 16 ) . forEach ( function ( n ) {
var d = ( n & 1 ) ? 'd' : 'n' , dk = d === 'd' ;
var c = ( n & 2 ) ? 'd' : 'n' , dj = c === 'd' ;
var b = ( n & 4 ) ? 'd' : 'n' , di = b === 'd' ;
var a = ( n & 8 ) ? 'd' : 'n' , dh = a === 'd' ;
var f , sheet , addr ;
if ( dh ) { f = paths . dt1 ; sheet = 'Sheet1' ; addr = 'B5' ; }
else { f = paths . nf1 ; sheet = '2011' ; addr = 'J36' ; }
it ( '[' + a + '] -> (' + b + ') -> [' + c + '] -> (' + d + ')' , function ( ) {
var wb1 = X . readFile ( f , { cellNF : true , cellDates : di , WTF : opts . WTF } ) ;
var wb2 = X . read ( X . write ( wb1 , { type : 'binary' , cellDates : dj , WTF : opts . WTF } ) , { type : 'binary' , cellDates : dk , WTF : opts . WTF } ) ;
var m = [ wb1 , wb2 ] . map ( function ( x ) { return x . Sheets [ sheet ] [ addr ] ; } ) ;
assert . equal ( m [ 0 ] . w , m [ 1 ] . w ) ;
/* wb1 cellDates */
if ( dh && di ) assert . equal ( m [ 0 ] . t , 'd' ) ;
//else if(a !== 'd' && di) assert.equal(m[0].t, 'd'); /* TODO */
else assert . equal ( m [ 0 ] . t , 'n' ) ;
/* wb2 cellDates */
if ( dh && di && dj && dk ) assert . equal ( m [ 1 ] . t , 'd' ) ;
else if ( dj && dk && ! di ) ; /* TODO: convert to date */
else assert . equal ( m [ 1 ] . t , 'n' ) ;
if ( m [ 0 ] . t === m [ 1 ] . t ) assert . equal ( m [ 0 ] . v , m [ 1 ] . v ) ;
else if ( m [ 0 ] . t === 'd' ) assert ( Math . abs ( datenum ( new Date ( m [ 0 ] . v ) ) - m [ 1 ] . v ) ) < . 01 ; /* TODO: 1sec adjustment */
} ) ;
} ) ;
} ) ;
2014-05-16 00:33:34 +00:00
/* the XLSJS require should not cause the test suite to fail */
var XLSJS ;
try {
XLSJS = require ( 'xlsjs' ) ;
var xls = XLSJS . readFile ( './test_files/formula_stress_test.xls' ) ;
var xml = XLSJS . readFile ( './test_files/formula_stress_test.xls.xml' ) ;
} catch ( e ) { return ; }
describe ( 'xlsjs conversions' , function ( ) { [
[ 'XLS' , 'formula_stress_test.xls' ] ,
[ 'XML' , 'formula_stress_test.xls.xml' ]
] . forEach ( function ( w ) {
it ( 'should be able to write ' + w [ 0 ] + ' files from xlsjs' , function ( ) {
2014-05-22 12:16:51 +00:00
var xls = XLSJS . readFile ( './test_files/' + w [ 1 ] , { cellNF : true } ) ;
X . writeFile ( xls , './tmp/' + w [ 1 ] + '.xlsx' , { bookSST : true } ) ;
X . writeFile ( xls , './tmp/' + w [ 1 ] + '.xlsb' , { bookSST : true } ) ;
2014-05-16 00:33:34 +00:00
} ) ;
} ) ;
2014-03-29 02:05:50 +00:00
} ) ;
2014-05-16 00:33:34 +00:00
} ) ;
describe ( 'invalid files' , function ( ) {
describe ( 'parse' , function ( ) { [
[ 'passwords' , 'excel-reader-xlsx_error03.xlsx' ] ,
[ 'XLS files' , 'roo_type_excel.xlsx' ] ,
[ 'DOC files' , 'word_doc.doc' ]
2014-05-22 12:16:51 +00:00
] . forEach ( function ( w ) { it ( 'should fail on ' + w [ 0 ] , function ( ) {
assert . throws ( function ( ) { X . readFile ( dir + w [ 1 ] ) ; } ) ;
assert . throws ( function ( ) { X . read ( fs . readFileSync ( dir + w [ 1 ] , 'base64' ) , { type : 'base64' } ) ; } ) ;
2014-05-31 15:44:56 +00:00
} ) ; } ) ;
2014-05-16 00:33:34 +00:00
} ) ;
describe ( 'write' , function ( ) {
it ( 'should pass' , function ( ) { X . write ( X . readFile ( paths . fst1 ) , { type : 'binary' } ) ; } ) ;
it ( 'should pass if a sheet is missing' , function ( ) {
var wb = X . readFile ( paths . fst1 ) ; delete wb . Sheets [ wb . SheetNames [ 0 ] ] ;
X . read ( X . write ( wb , { type : 'binary' } ) , { type : 'binary' } ) ;
} ) ;
2014-05-22 12:16:51 +00:00
[ 'Props' , 'Custprops' , 'SSF' ] . forEach ( function ( t ) {
it ( 'should pass if ' + t + ' is missing' , function ( ) {
var wb = X . readFile ( paths . fst1 ) ;
assert . doesNotThrow ( function ( ) {
delete wb [ t ] ;
X . write ( wb , { type : 'binary' } ) ;
} ) ;
2014-05-16 00:33:34 +00:00
} ) ;
} ) ;
2014-05-22 12:16:51 +00:00
[ 'SheetNames' , 'Sheets' ] . forEach ( function ( t ) {
it ( 'should fail if ' + t + ' is missing' , function ( ) {
var wb = X . readFile ( paths . fst1 ) ;
assert . throws ( function ( ) {
delete wb [ t ] ;
X . write ( wb , { type : 'binary' } ) ;
} ) ;
2014-05-16 00:33:34 +00:00
} ) ;
} ) ;
2014-03-29 02:05:50 +00:00
} ) ;
} ) ;
2014-05-29 22:30:03 +00:00
function datenum ( v , date1904 ) {
if ( date1904 ) v += 1462 ;
var epoch = Date . parse ( v ) ;
return ( epoch - new Date ( Date . UTC ( 1899 , 11 , 30 ) ) ) / ( 24 * 60 * 60 * 1000 ) ;
}
function sheet _from _array _of _arrays ( data , opts ) {
var ws = { } ;
var range = { s : { c : 10000000 , r : 10000000 } , e : { c : 0 , r : 0 } } ;
for ( var R = 0 ; R != data . length ; ++ R ) {
for ( var C = 0 ; C != data [ R ] . length ; ++ C ) {
if ( range . s . r > R ) range . s . r = R ;
if ( range . s . c > C ) range . s . c = C ;
2014-05-31 15:44:56 +00:00
if ( range . e . r < R ) range . e . r = R ;
2014-05-29 22:30:03 +00:00
if ( range . e . c < C ) range . e . c = C ;
var cell = { v : data [ R ] [ C ] } ;
if ( cell . v == null ) continue ;
var cell _ref = X . utils . encode _cell ( { c : C , r : R } ) ;
if ( typeof cell . v === 'number' ) cell . t = 'n' ;
else if ( typeof cell . v === 'boolean' ) cell . t = 'b' ;
else if ( cell . v instanceof Date ) {
cell . t = 'n' ; cell . z = X . SSF . _table [ 14 ] ;
cell . v = datenum ( cell . v ) ;
}
else cell . t = 's' ;
ws [ cell _ref ] = cell ;
}
}
if ( range . s . c < 10000000 ) ws [ '!ref' ] = X . utils . encode _range ( range ) ;
return ws ;
}
describe ( 'json output' , function ( ) {
function seeker ( json , keys , val ) {
for ( var i = 0 ; i != json . length ; ++ i ) {
for ( var j = 0 ; j != keys . length ; ++ j ) {
if ( json [ i ] [ keys [ j ] ] === val ) throw new Error ( "found " + val + " in row " + i + " key " + keys [ j ] ) ;
}
}
}
var data , ws ;
before ( function ( ) {
data = [
[ 1 , 2 , 3 ] ,
[ true , false , null , "sheetjs" ] ,
[ "foo" , "bar" , new Date ( "2014-02-19T14:30Z" ) , "0.3" ] ,
[ "baz" , null , "qux" ]
] ;
ws = sheet _from _array _of _arrays ( data ) ;
} ) ;
it ( 'should use first-row headers and full sheet by default' , function ( ) {
var json = X . utils . sheet _to _json ( ws ) ;
assert . equal ( json . length , data . length - 1 ) ;
assert . equal ( json [ 0 ] [ 1 ] , true ) ;
assert . equal ( json [ 1 ] [ 2 ] , "bar" ) ;
assert . equal ( json [ 2 ] [ 3 ] , "qux" ) ;
assert . doesNotThrow ( function ( ) { seeker ( json , [ 1 , 2 , 3 ] , "sheetjs" ) ; } ) ;
assert . throws ( function ( ) { seeker ( json , [ 1 , 2 , 3 ] , "baz" ) ; } ) ;
} ) ;
it ( 'should create array of arrays if header == 1' , function ( ) {
var json = X . utils . sheet _to _json ( ws , { header : 1 } ) ;
assert . equal ( json . length , data . length ) ;
assert . equal ( json [ 1 ] [ 0 ] , true ) ;
assert . equal ( json [ 2 ] [ 1 ] , "bar" ) ;
assert . equal ( json [ 3 ] [ 2 ] , "qux" ) ;
assert . doesNotThrow ( function ( ) { seeker ( json , [ 0 , 1 , 2 ] , "sheetjs" ) ; } ) ;
assert . throws ( function ( ) { seeker ( json , [ 0 , 1 , 2 , 3 ] , "sheetjs" ) ; } ) ;
assert . throws ( function ( ) { seeker ( json , [ 0 , 1 , 2 ] , "baz" ) ; } ) ;
} ) ;
it ( 'should use column names if header == "A"' , function ( ) {
var json = X . utils . sheet _to _json ( ws , { header : 'A' } ) ;
assert . equal ( json . length , data . length ) ;
assert . equal ( json [ 1 ] [ 'A' ] , true ) ;
assert . equal ( json [ 2 ] [ 'B' ] , "bar" ) ;
assert . equal ( json [ 3 ] [ 'C' ] , "qux" ) ;
assert . doesNotThrow ( function ( ) { seeker ( json , "ABC" , "sheetjs" ) ; } ) ;
assert . throws ( function ( ) { seeker ( json , "ABCD" , "sheetjs" ) ; } ) ;
assert . throws ( function ( ) { seeker ( json , "ABC" , "baz" ) ; } ) ;
} ) ;
it ( 'should use column labels if specified' , function ( ) {
var json = X . utils . sheet _to _json ( ws , { header : [ "O" , "D" , "I" , "N" ] } ) ;
assert . equal ( json . length , data . length ) ;
assert . equal ( json [ 1 ] [ 'O' ] , true ) ;
assert . equal ( json [ 2 ] [ 'D' ] , "bar" ) ;
assert . equal ( json [ 3 ] [ 'I' ] , "qux" ) ;
assert . doesNotThrow ( function ( ) { seeker ( json , "ODI" , "sheetjs" ) ; } ) ;
assert . throws ( function ( ) { seeker ( json , "ODIN" , "sheetjs" ) ; } ) ;
assert . throws ( function ( ) { seeker ( json , "ODIN" , "baz" ) ; } ) ;
} ) ;
[ [ "string" , "A2:D4" ] , [ "numeric" , 1 ] , [ "object" , { s : { r : 1 , c : 0 } , e : { r : 3 , c : 3 } } ] ] . forEach ( function ( w ) {
it ( 'should accept custom ' + w [ 0 ] + ' range' , function ( ) {
var json = X . utils . sheet _to _json ( ws , { header : 1 , range : w [ 1 ] } ) ;
assert . equal ( json . length , 3 ) ;
assert . equal ( json [ 0 ] [ 0 ] , true ) ;
assert . equal ( json [ 1 ] [ 1 ] , "bar" ) ;
assert . equal ( json [ 2 ] [ 2 ] , "qux" ) ;
assert . doesNotThrow ( function ( ) { seeker ( json , [ 0 , 1 , 2 ] , "sheetjs" ) ; } ) ;
assert . throws ( function ( ) { seeker ( json , [ 0 , 1 , 2 , 3 ] , "sheetjs" ) ; } ) ;
assert . throws ( function ( ) { seeker ( json , [ 0 , 1 , 2 ] , "baz" ) ; } ) ;
} ) ;
} ) ;
} ) ;
describe ( 'corner cases' , function ( ) {
it ( 'output functions' , function ( ) {
var data = [
[ 1 , 2 , 3 ] ,
[ true , false , null , "sheetjs" ] ,
[ "foo" , "bar" , new Date ( "2014-02-19T14:30Z" ) , "0.3" ] ,
[ "baz" , null , "q\"ux" ]
] ;
ws = sheet _from _array _of _arrays ( data ) ;
ws . A1 . f = "" ; ws . A1 . w = "" ;
delete ws . C3 . w ; delete ws . C3 . z ; ws . C3 . XF = { ifmt : 14 } ;
ws . A4 . t = "e" ;
X . utils . get _formulae ( ws ) ;
X . utils . make _csv ( ws ) ;
X . utils . make _json ( ws ) ;
2014-06-05 07:06:20 +00:00
ws [ '!cols' ] = [ { wch : 6 } , { wch : 7 } , { wch : 10 } , { wch : 20 } ] ;
var wb = { SheetNames : [ 'sheetjs' ] , Sheets : { sheetjs : ws } } ;
X . write ( wb , { type : "binary" , bookType : 'xlsx' } ) ;
X . write ( wb , { type : "buffer" , bookType : 'xlsm' } ) ;
X . write ( wb , { type : "base64" , bookType : 'xlsb' } ) ;
2014-05-29 22:30:03 +00:00
ws . A2 . t = "f" ;
assert . throws ( function ( ) { X . utils . make _json ( ws ) ; } ) ;
} ) ;
it ( 'SSF' , function ( ) {
X . SSF . format ( "General" , "dafuq" ) ;
assert . throws ( function ( x ) { return X . SSF . format ( "General" , { sheet : "js" } ) ; } ) ;
X . SSF . format ( "b e ddd hh AM/PM" , 41722.4097222222 ) ;
X . SSF . format ( "b ddd hh m" , 41722.4097222222 ) ;
[ "hhh" , "hhh A/P" , "hhmmm" , "sss" , "[hhh]" , "G eneral" ] . forEach ( function ( f ) {
assert . throws ( function ( x ) { return X . SSF . format ( f , 12345.6789 ) ; } ) ;
} ) ;
[ "[m]" , "[s]" ] . forEach ( function ( f ) {
assert . doesNotThrow ( function ( x ) { return X . SSF . format ( f , 12345.6789 ) ; } ) ;
} ) ;
} ) ;
2014-06-05 07:06:20 +00:00
it ( 'SSF oddities' , function ( ) {
var ssfdata = require ( './misc/ssf.json' ) ;
ssfdata . forEach ( function ( d ) {
2014-06-29 18:29:45 +00:00
for ( var j = 1 ; j < d . length ; ++ j ) {
2014-06-05 07:06:20 +00:00
if ( d [ j ] . length == 2 ) {
var expected = d [ j ] [ 1 ] , actual = X . SSF . format ( d [ 0 ] , d [ j ] [ 0 ] , { } ) ;
assert . equal ( actual , expected ) ;
} else if ( d [ j ] [ 2 ] !== "#" ) assert . throws ( function ( ) { SSF . format ( d [ 0 ] , d [ j ] [ 0 ] ) ; } ) ;
}
} ) ;
} ) ;
2014-05-29 22:30:03 +00:00
} ) ;