🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

@testivai/common

Package Overview
Dependencies
Maintainers
1
Versions
8
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@testivai/common - npm Package Compare versions

Comparing version
0.2.1
to
0.2.2
+1
dist/auth.d.ts.map
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAc5C;;GAEG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,iBAAiB,GAAG,IAAI,CAKpE;AAED;;;GAGG;AACH,wBAAgB,eAAe,IAAI,iBAAiB,GAAG,IAAI,CAU1D;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAIxC;AAED;;;GAGG;AACH,wBAAgB,SAAS,IAAI,MAAM,GAAG,IAAI,CAUzC;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,OAAO,CAEzC"}
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsBH,0CAKC;AAMD,0CAUC;AAKD,8CAIC;AAMD,8BAUC;AAKD,0CAEC;AAzED,uCAAyB;AACzB,2CAA6B;AAC7B,uCAAyB;AAGzB,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,WAAW,CAAC,CAAC;AAC7D,MAAM,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,aAAa,CAAC,CAAC;AAEnE;;GAEG;AACH,SAAS,oBAAoB;IAC3B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;QACpC,EAAE,CAAC,SAAS,CAAC,eAAe,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAClE,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAgB,eAAe,CAAC,WAA8B;IAC5D,oBAAoB,EAAE,CAAC;IACvB,EAAE,CAAC,aAAa,CAAC,gBAAgB,EAAE,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE;QACvE,IAAI,EAAE,KAAK;KACZ,CAAC,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,SAAgB,eAAe;IAC7B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,gBAAgB,CAAC,EAAE,CAAC;QACrC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,gBAAgB,EAAE,OAAO,CAAC,CAAC;QAC3D,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAsB,CAAC;IAClD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAgB,iBAAiB;IAC/B,IAAI,EAAE,CAAC,UAAU,CAAC,gBAAgB,CAAC,EAAE,CAAC;QACpC,EAAE,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAC;IAClC,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,SAAgB,SAAS;IACvB,mCAAmC;IACnC,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;IAC5C,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,kCAAkC;IAClC,MAAM,WAAW,GAAG,eAAe,EAAE,CAAC;IACtC,OAAO,WAAW,EAAE,MAAM,IAAI,IAAI,CAAC;AACrC,CAAC;AAED;;GAEG;AACH,SAAgB,eAAe;IAC7B,OAAO,SAAS,EAAE,KAAK,IAAI,CAAC;AAC9B,CAAC"}
{"version":3,"file":"compression.d.ts","sourceRoot":"","sources":["../src/compression.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,MAAM,WAAW,kBAAkB;IACjC,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,OAAO,CAA+B;gBAElC,OAAO,GAAE,kBAAuB;IAQ5C;;OAEG;IACG,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAoCxD;;OAEG;IACH,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAMlC;;OAEG;IACH,oBAAoB,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI;CAQtD;AAED,eAAO,MAAM,iBAAiB,mBAA0B,CAAC"}
{"version":3,"file":"compression.js","sourceRoot":"","sources":["../src/compression.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEH,2CAA6B;AAC7B,+BAAiC;AAEjC,MAAM,SAAS,GAAG,IAAA,gBAAS,EAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAiBvC,MAAa,iBAAiB;IAG5B,YAAY,UAA8B,EAAE;QAC1C,IAAI,CAAC,OAAO,GAAG;YACb,eAAe,EAAE,OAAO,CAAC,eAAe,KAAK,KAAK,EAAE,gBAAgB;YACpE,gBAAgB,EAAE,OAAO,CAAC,gBAAgB,IAAI,CAAC;YAC/C,oBAAoB,EAAE,OAAO,CAAC,oBAAoB,IAAI,CAAC,GAAG,IAAI,GAAG,IAAI,EAAE,MAAM;SAC9E,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,QAAQ,CAAC,IAAY;QACzB,MAAM,YAAY,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QAC7C,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAE7B,gDAAgD;QAChD,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,eAAe,IAAI,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,oBAAoB,EAAE,CAAC;YACtF,OAAO;gBACL,IAAI;gBACJ,YAAY;gBACZ,cAAc,EAAE,YAAY;gBAC5B,gBAAgB,EAAE,CAAC;gBACnB,eAAe,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;aACxC,CAAC;QACJ,CAAC;QAED,oBAAoB;QACpB,MAAM,cAAc,GAAG,MAAM,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;YACxD,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,gBAAgB;SACrC,CAAC,CAAC;QAEH,MAAM,eAAe,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;QAC/C,MAAM,gBAAgB,GAAG,CAAC,GAAG,cAAc,CAAC,MAAM,GAAG,YAAY,CAAC;QAElE,OAAO;YACL,IAAI,EAAE,cAAc;YACpB,OAAO,EAAE;gBACP,kBAAkB,EAAE,MAAM;gBAC1B,cAAc,EAAE,kBAAkB;aACnC;YACD,YAAY;YACZ,cAAc,EAAE,cAAc,CAAC,MAAM;YACrC,gBAAgB;YAChB,eAAe;SAChB,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,WAAW,CAAC,KAAa;QACvB,IAAI,KAAK,GAAG,IAAI;YAAE,OAAO,KAAK,GAAG,IAAI,CAAC;QACtC,IAAI,KAAK,GAAG,IAAI,GAAG,IAAI;YAAE,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC;QAClE,OAAO,CAAC,KAAK,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC;IACpD,CAAC;IAED;;OAEG;IACH,oBAAoB,CAAC,MAAyB;QAC5C,IAAI,MAAM,CAAC,gBAAgB,GAAG,CAAC,EAAE,CAAC;YAChC,OAAO,CAAC,GAAG,CACT,wCAAwC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,YAAY,CAAC,KAAK;gBAClF,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,MAAM,CAAC,gBAAgB,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,gBAAgB,MAAM,CAAC,eAAe,KAAK,CACrI,CAAC;QACJ,CAAC;IACH,CAAC;CACF;AAtED,8CAsEC;AAEY,QAAA,iBAAiB,GAAG,IAAI,iBAAiB,EAAE,CAAC"}
{"version":3,"file":"config-loader.d.ts","sourceRoot":"","sources":["../src/config-loader.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAIzC;;GAEG;AACH,eAAO,MAAM,cAAc,EAAE,cAM5B,CAAC;AAEF;;GAEG;AACH,wBAAgB,cAAc,CAAC,QAAQ,GAAE,MAAsB,GAAG,MAAM,GAAG,IAAI,CAc9E;AAED;;;GAGG;AACH,wBAAsB,UAAU,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAqB7E;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,GAAG,GAAE,MAAsB,GAAG,OAAO,CAOjE;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,cAAc,EAAE,OAAO,GAAE,MAAsB,GAAG,MAAM,CAG5F"}
{"version":3,"file":"config-loader.js","sourceRoot":"","sources":["../src/config-loader.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsBH,wCAcC;AAMD,gCAqBC;AAKD,oCAOC;AAKD,oCAGC;AAjFD,uCAAyB;AACzB,2CAA6B;AAG7B,MAAM,iBAAiB,GAAG,CAAC,oBAAoB,EAAE,oBAAoB,CAAC,CAAC;AAEvE;;GAEG;AACU,QAAA,cAAc,GAAmB;IAC5C,SAAS,EAAE,gBAAgB;IAC3B,QAAQ,EAAE;QACR,KAAK,EAAE,IAAI;QACX,MAAM,EAAE,GAAG;KACZ;CACF,CAAC;AAEF;;GAEG;AACH,SAAgB,cAAc,CAAC,WAAmB,OAAO,CAAC,GAAG,EAAE;IAC7D,IAAI,UAAU,GAAG,QAAQ,CAAC;IAE1B,OAAO,UAAU,KAAK,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/C,KAAK,MAAM,QAAQ,IAAI,iBAAiB,EAAE,CAAC;YACzC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;YACnD,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;gBAC9B,OAAO,UAAU,CAAC;YACpB,CAAC;QACH,CAAC;QACD,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACxC,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;GAGG;AACI,KAAK,UAAU,UAAU,CAAC,UAAmB;IAClD,MAAM,YAAY,GAAG,UAAU,IAAI,cAAc,EAAE,CAAC;IAEpD,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO,sBAAc,CAAC;IACxB,CAAC;IAED,IAAI,CAAC;QACH,sDAAsD;QACtD,kEAAkE;QAClE,MAAM,YAAY,GAAG,yBAAa,YAAY,uCAAC,CAAC;QAChD,MAAM,UAAU,GAAG,YAAY,CAAC,OAAO,IAAI,YAAY,CAAC;QAExD,OAAO;YACL,GAAG,sBAAc;YACjB,GAAG,UAAU;SACd,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,IAAI,CAAC,uCAAuC,YAAY,mBAAmB,CAAC,CAAC;QACrF,OAAO,sBAAc,CAAC;IACxB,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAgB,YAAY,CAAC,MAAc,OAAO,CAAC,GAAG,EAAE;IACtD,KAAK,MAAM,QAAQ,IAAI,iBAAiB,EAAE,CAAC;QACzC,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC;YAC5C,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,SAAgB,YAAY,CAAC,MAAsB,EAAE,UAAkB,OAAO,CAAC,GAAG,EAAE;IAClF,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,IAAI,sBAAc,CAAC,SAAU,CAAC;IAChE,OAAO,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;AAChF,CAAC"}
{"version":3,"file":"core-api-client.d.ts","sourceRoot":"","sources":["../src/core-api-client.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,wBAAwB,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAInF,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,MAAM,CAAS;gBAEX,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM;IAY5C;;OAEG;IACG,cAAc,IAAI,OAAO,CAAC,wBAAwB,CAAC;IAwBzD;;;;OAIG;IACG,iBAAiB,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAOtE;;OAEG;IACG,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;CAYtE;AAED,eAAO,MAAM,oBAAoB,+BAAkB,CAAC"}
{"version":3,"file":"core-api-client.js","sourceRoot":"","sources":["../src/core-api-client.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEH,+CAAyD;AAGzD,MAAM,eAAe,GAAG,4BAA4B,CAAC;AAErD,MAAa,aAAa;IAIxB,YAAY,MAAc,EAAE,OAAgB;QAC1C,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,MAAM,GAAG,eAAK,CAAC,MAAM,CAAC;YACzB,OAAO,EAAE,OAAO,IAAI,eAAe;YACnC,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,WAAW,EAAE,MAAM;aACpB;YACD,OAAO,EAAE,KAAK;SACf,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,cAAc;QAClB,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;YACpE,OAAO;gBACL,KAAK,EAAE,IAAI;gBACX,SAAS,EAAE,QAAQ,CAAC,IAAI,CAAC,UAAU;gBACnC,WAAW,EAAE,QAAQ,CAAC,IAAI,CAAC,YAAY;gBACvC,cAAc,EAAE,QAAQ,CAAC,IAAI,CAAC,eAAe;gBAC7C,gBAAgB,EAAE,QAAQ,CAAC,IAAI,CAAC,iBAAiB;aAClD,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,kBAAU,EAAE,CAAC;gBAChC,IAAI,KAAK,CAAC,QAAQ,EAAE,MAAM,KAAK,GAAG,EAAE,CAAC;oBACnC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,iBAAiB,EAAE,CAAC;gBACpD,CAAC;gBACD,IAAI,KAAK,CAAC,QAAQ,EAAE,MAAM,KAAK,GAAG,EAAE,CAAC;oBACnC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,gCAAgC,EAAE,CAAC;gBACnE,CAAC;gBACD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;YAChD,CAAC;YACD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,wBAAwB,EAAE,CAAC;QAC3D,CAAC;IACH,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,iBAAiB,CAAC,IAAiB;QACvC,MAAM,IAAI,KAAK,CACb,qFAAqF;YACrF,6GAA6G,CAC9G,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,gBAAgB,CAAC,SAAiB;QACtC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,qBAAqB,SAAS,EAAE,CAAC,CAAC;QACzE,OAAO;YACL,SAAS,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE;YAC3B,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,MAAM;YAC5B,OAAO,EAAE,QAAQ,CAAC,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,KAAK,QAAQ;YACpE,OAAO,EAAE,QAAQ,CAAC,IAAI,CAAC,QAAQ;YAC/B,YAAY,EAAE,QAAQ,CAAC,IAAI,CAAC,aAAa;YACzC,aAAa,EAAE,QAAQ,CAAC,IAAI,CAAC,cAAc;YAC3C,cAAc,EAAE,QAAQ,CAAC,IAAI,CAAC,eAAe;SAC9C,CAAC;IACJ,CAAC;CACF;AAtED,sCAsEC;AAEY,QAAA,oBAAoB,GAAG,eAAe,CAAC"}
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,cAAc,SAAS,CAAC;AAGxB,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAGxE,OAAO,EACL,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,SAAS,EACT,eAAe,GAChB,MAAM,QAAQ,CAAC;AAGhB,OAAO,EACL,cAAc,EACd,cAAc,EACd,UAAU,EACV,YAAY,EACZ,YAAY,GACb,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAG/C,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,GACvB,MAAM,eAAe,CAAC"}
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;;;;;;AAEH,QAAQ;AACR,0CAAwB;AAExB,kBAAkB;AAClB,qDAAwE;AAA/D,gHAAA,aAAa,OAAA;AAAE,uHAAA,oBAAoB,OAAA;AAE5C,iBAAiB;AACjB,+BAMgB;AALd,uGAAA,eAAe,OAAA;AACf,uGAAA,eAAe,OAAA;AACf,yGAAA,iBAAiB,OAAA;AACjB,iGAAA,SAAS,OAAA;AACT,uGAAA,eAAe,OAAA;AAGjB,gBAAgB;AAChB,iDAMyB;AALvB,+GAAA,cAAc,OAAA;AACd,+GAAA,cAAc,OAAA;AACd,2GAAA,UAAU,OAAA;AACV,6GAAA,YAAY,OAAA;AACZ,6GAAA,YAAY,OAAA;AAGd,oCAAoC;AACpC,uCAA+C;AAAtC,oGAAA,QAAQ,OAAA;AAAE,mGAAA,OAAO,OAAA;AAE1B,wBAAwB;AACxB,6CAKuB;AAJrB,gHAAA,iBAAiB,OAAA;AACjB,gHAAA,iBAAiB,OAAA"}
{"version":3,"file":"testivai.d.ts","sourceRoot":"","sources":["../src/testivai.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEvC;;;;;GAKG;AACH,wBAAsB,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAqCrE;AAED;;;;GAIG;AACH,eAAO,MAAM,QAAQ;;CAEpB,CAAC"}
{"version":3,"file":"testivai.js","sourceRoot":"","sources":["../src/testivai.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;;AAYH,0BAqCC;AA/CD,uDAAkD;AAClD,iCAAmC;AAGnC;;;;;GAKG;AACI,KAAK,UAAU,OAAO,CAAC,IAAU,EAAE,IAAY;IACpD,MAAM,MAAM,GAAG,IAAA,gBAAS,GAAE,CAAC;IAE3B,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,+DAA+D,CAAC,CAAC;IACnF,CAAC;IAED,kBAAkB;IAClB,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;IAE7D,wBAAwB;IACxB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;IAElC,qBAAqB;IACrB,MAAM,MAAM,GAAG,IAAI,+BAAa,CAAC,MAAM,CAAC,CAAC;IAEzC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,iBAAiB,CAAC;YAC5C,IAAI;YACJ,GAAG;YACH,UAAU;YACV,IAAI;YACJ,QAAQ,EAAE,IAAI,CAAC,YAAY,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE;SAC9D,CAAC,CAAC;QAEH,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,6BAA6B,IAAI,uBAAuB,MAAM,CAAC,YAAY,IAAI,6BAA6B,EAAE,CAAC,CAAC;QAClI,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,0BAA0B,IAAI,EAAE,CAAC,CAAC;IAChD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;YAC3B,MAAM,KAAK,CAAC;QACd,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,kCAAkC,KAAK,EAAE,CAAC,CAAC;IAC7D,CAAC;AACH,CAAC;AAED;;;;GAIG;AACU,QAAA,QAAQ,GAAG;IACtB,OAAO;CACR,CAAC"}
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";AAAA;;GAEG"}
MIT License
Copyright (c) 2025 TestivAI
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
# @testivai/common
Shared utilities for TestivAI SDKs and CLI.
This package is part of [testivai-oss](https://github.com/mcbuddy/testivai-oss). It is typically consumed transitively via `@testivai/witness` or `@testivai/witness-playwright` — you don't usually need to install it directly.
## Exports
- `CoreApiClient`, `DEFAULT_CORE_API_URL` — optional cloud API client
- `getApiKey`, `saveCredentials`, `loadCredentials`, `deleteCredentials`, `isAuthenticated` — credential helpers
- `loadConfig`, `findConfigFile`, `configExists`, `getOutputDir`, `DEFAULT_CONFIG` — config loader
- `CompressionHelper`, `compressionHelper` — GZIP helpers
- `testivai`, `witness` — optional Playwright helper (requires `playwright` peer dependency)
## Installation
```bash
npm install @testivai/common
```
## License
MIT
+1
-0

@@ -28,1 +28,2 @@ /**

export declare function isAuthenticated(): boolean;
//# sourceMappingURL=auth.d.ts.map

@@ -111,1 +111,2 @@ "use strict";

}
//# sourceMappingURL=auth.js.map

@@ -35,1 +35,2 @@ /**

export declare const compressionHelper: CompressionHelper;
//# sourceMappingURL=compression.d.ts.map

@@ -108,1 +108,2 @@ "use strict";

exports.compressionHelper = new CompressionHelper();
//# sourceMappingURL=compression.js.map

@@ -27,1 +27,2 @@ /**

export declare function getOutputDir(config: TestivaiConfig, baseDir?: string): string;
//# sourceMappingURL=config-loader.d.ts.map

@@ -116,1 +116,2 @@ "use strict";

}
//# sourceMappingURL=config-loader.js.map

@@ -26,1 +26,2 @@ /**

export declare const DEFAULT_CORE_API_URL = "https://core-api.testiv.ai";
//# sourceMappingURL=core-api-client.d.ts.map

@@ -109,1 +109,2 @@ "use strict";

exports.DEFAULT_CORE_API_URL = DEFAULT_API_URL;
//# sourceMappingURL=core-api-client.js.map

@@ -11,1 +11,2 @@ /**

export { CompressionHelper, compressionHelper, type CompressionOptions, type CompressionResult, } from './compression';
//# sourceMappingURL=index.d.ts.map

@@ -50,1 +50,2 @@ "use strict";

Object.defineProperty(exports, "compressionHelper", { enumerable: true, get: function () { return compression_1.compressionHelper; } });
//# sourceMappingURL=index.js.map

@@ -25,1 +25,2 @@ /**

};
//# sourceMappingURL=testivai.d.ts.map

@@ -61,1 +61,2 @@ "use strict";

};
//# sourceMappingURL=testivai.js.map

@@ -134,1 +134,2 @@ /**

export type CDPerformanceMetrics = BrowserPerformanceMetrics;
//# sourceMappingURL=types.d.ts.map

@@ -6,1 +6,2 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=types.js.map
+29
-13
{
"name": "@testivai/common",
"version": "0.2.1",
"version": "0.2.2",
"description": "Shared utilities for TestivAI SDKs and CLI",

@@ -10,10 +10,7 @@ "main": "dist/index.js",

},
"scripts": {
"build": "tsc",
"clean": "rm -rf dist",
"prepublishOnly": "npm run build",
"test": "jest",
"test:unit": "jest",
"test:watch": "jest --watch"
},
"files": [
"dist",
"README.md",
"LICENSE"
],
"keywords": [

@@ -24,7 +21,19 @@ "testivai",

],
"author": "",
"author": "TestivAI",
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/mcbuddy/testivai-oss.git",
"directory": "packages/common"
},
"bugs": {
"url": "https://github.com/mcbuddy/testivai-oss/issues"
},
"homepage": "https://github.com/mcbuddy/testivai-oss/tree/main/packages/common#readme",
"publishConfig": {
"access": "public"
},
"engines": {
"node": ">=18.0.0"
},
"dependencies": {

@@ -34,7 +43,7 @@ "axios": "^1.6.0"

"devDependencies": {
"@types/jest": "^30.0.0",
"@types/node": "^20.10.0",
"@types/jest": "^30.0.0",
"jest": "^30.2.0",
"playwright": "^1.40.0",
"ts-jest": "^29.4.5",
"playwright": "^1.40.0",
"typescript": "^5.3.0"

@@ -49,3 +58,10 @@ },

}
},
"scripts": {
"build": "tsc",
"clean": "rm -rf dist",
"test": "jest",
"test:unit": "jest",
"test:watch": "jest --watch"
}
}
}
/**
* Tests for compression utilities
*/
export {};
"use strict";
/**
* Tests for compression utilities
*/
Object.defineProperty(exports, "__esModule", { value: true });
const compression_1 = require("../compression");
describe('CompressionHelper', () => {
let compressionHelper;
beforeEach(() => {
compressionHelper = new compression_1.CompressionHelper();
});
describe('compress', () => {
it('should not compress small data below threshold', async () => {
const smallData = JSON.stringify({ test: 'small data' });
const result = await compressionHelper.compress(smallData);
expect(result.compressionRatio).toBe(0);
expect(result.originalSize).toBe(result.compressedSize);
expect(typeof result.data).toBe('string');
expect(result.headers).toBeUndefined();
});
it('should compress large data above threshold', async () => {
// Create data larger than 5MB threshold (using smaller threshold for test)
const testHelper = new compression_1.CompressionHelper({ compressionThreshold: 100 });
const largeData = 'x'.repeat(1000);
const result = await testHelper.compress(largeData);
expect(result.compressionRatio).toBeGreaterThan(0);
expect(result.compressedSize).toBeLessThan(result.originalSize);
expect(Buffer.isBuffer(result.data)).toBe(true);
expect(result.headers).toEqual({
'Content-Encoding': 'gzip',
'Content-Type': 'application/json',
});
});
it('should respect compression disabled option', async () => {
const testHelper = new compression_1.CompressionHelper({ compressUploads: false });
const largeData = 'x'.repeat(1000);
const result = await testHelper.compress(largeData);
expect(result.compressionRatio).toBe(0);
expect(result.originalSize).toBe(result.compressedSize);
});
it('should use custom compression level', async () => {
const testHelper = new compression_1.CompressionHelper({
compressionThreshold: 100,
compressionLevel: 9 // Maximum compression
});
const largeData = 'x'.repeat(1000);
const result = await testHelper.compress(largeData);
expect(result.compressionRatio).toBeGreaterThan(0);
expect(result.compressionTime).toBeGreaterThanOrEqual(0);
});
});
describe('formatBytes', () => {
it('should format bytes correctly', () => {
expect(compressionHelper.formatBytes(512)).toBe('512 B');
expect(compressionHelper.formatBytes(1536)).toBe('1.5 KB');
expect(compressionHelper.formatBytes(1048576)).toBe('1.0 MB');
});
});
describe('logCompressionResult', () => {
it('should log compression result when compressed', () => {
const consoleSpy = jest.spyOn(console, 'log').mockImplementation();
const result = {
data: Buffer.from('compressed'),
originalSize: 1000,
compressedSize: 100,
compressionRatio: 0.9,
compressionTime: 50,
};
compressionHelper.logCompressionResult(result);
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('Compressed batch: 1000 B → 100 B (90.0% reduction, 50ms)'));
consoleSpy.mockRestore();
});
it('should not log when not compressed', () => {
const consoleSpy = jest.spyOn(console, 'log').mockImplementation();
const result = {
data: 'uncompressed',
originalSize: 50,
compressedSize: 50,
compressionRatio: 0,
compressionTime: 0,
};
compressionHelper.logCompressionResult(result);
// Should not log when compression ratio is 0
expect(consoleSpy).not.toHaveBeenCalled();
consoleSpy.mockRestore();
});
});
});
/** @type {import('ts-jest').JestConfigWithTsJest} */
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
roots: ['<rootDir>/src'],
testMatch: ['**/__tests__/**/*.test.ts'],
collectCoverageFrom: [
'src/**/*.ts',
'!src/**/*.d.ts',
'!src/**/__tests__/**',
],
moduleFileExtensions: ['ts', 'js', 'json'],
testTimeout: 10000,
};
/**
* Tests for compression utilities
*/
import { CompressionHelper } from '../compression';
describe('CompressionHelper', () => {
let compressionHelper: CompressionHelper;
beforeEach(() => {
compressionHelper = new CompressionHelper();
});
describe('compress', () => {
it('should not compress small data below threshold', async () => {
const smallData = JSON.stringify({ test: 'small data' });
const result = await compressionHelper.compress(smallData);
expect(result.compressionRatio).toBe(0);
expect(result.originalSize).toBe(result.compressedSize);
expect(typeof result.data).toBe('string');
expect(result.headers).toBeUndefined();
});
it('should compress large data above threshold', async () => {
// Create data larger than 5MB threshold (using smaller threshold for test)
const testHelper = new CompressionHelper({ compressionThreshold: 100 });
const largeData = 'x'.repeat(1000);
const result = await testHelper.compress(largeData);
expect(result.compressionRatio).toBeGreaterThan(0);
expect(result.compressedSize).toBeLessThan(result.originalSize);
expect(Buffer.isBuffer(result.data)).toBe(true);
expect(result.headers).toEqual({
'Content-Encoding': 'gzip',
'Content-Type': 'application/json',
});
});
it('should respect compression disabled option', async () => {
const testHelper = new CompressionHelper({ compressUploads: false });
const largeData = 'x'.repeat(1000);
const result = await testHelper.compress(largeData);
expect(result.compressionRatio).toBe(0);
expect(result.originalSize).toBe(result.compressedSize);
});
it('should use custom compression level', async () => {
const testHelper = new CompressionHelper({
compressionThreshold: 100,
compressionLevel: 9 // Maximum compression
});
const largeData = 'x'.repeat(1000);
const result = await testHelper.compress(largeData);
expect(result.compressionRatio).toBeGreaterThan(0);
expect(result.compressionTime).toBeGreaterThanOrEqual(0);
});
});
describe('formatBytes', () => {
it('should format bytes correctly', () => {
expect(compressionHelper.formatBytes(512)).toBe('512 B');
expect(compressionHelper.formatBytes(1536)).toBe('1.5 KB');
expect(compressionHelper.formatBytes(1048576)).toBe('1.0 MB');
});
});
describe('logCompressionResult', () => {
it('should log compression result when compressed', () => {
const consoleSpy = jest.spyOn(console, 'log').mockImplementation();
const result = {
data: Buffer.from('compressed'),
originalSize: 1000,
compressedSize: 100,
compressionRatio: 0.9,
compressionTime: 50,
};
compressionHelper.logCompressionResult(result);
expect(consoleSpy).toHaveBeenCalledWith(
expect.stringContaining('Compressed batch: 1000 B → 100 B (90.0% reduction, 50ms)')
);
consoleSpy.mockRestore();
});
it('should not log when not compressed', () => {
const consoleSpy = jest.spyOn(console, 'log').mockImplementation();
const result = {
data: 'uncompressed',
originalSize: 50,
compressedSize: 50,
compressionRatio: 0,
compressionTime: 0,
};
compressionHelper.logCompressionResult(result);
// Should not log when compression ratio is 0
expect(consoleSpy).not.toHaveBeenCalled();
consoleSpy.mockRestore();
});
});
});
/**
* Authentication utilities for TestivAI
* Handles credential storage and retrieval
*/
import * as fs from 'fs';
import * as path from 'path';
import * as os from 'os';
import { StoredCredentials } from './types';
const CREDENTIALS_DIR = path.join(os.homedir(), '.testivai');
const CREDENTIALS_FILE = path.join(CREDENTIALS_DIR, 'credentials');
/**
* Ensure the credentials directory exists
*/
function ensureCredentialsDir(): void {
if (!fs.existsSync(CREDENTIALS_DIR)) {
fs.mkdirSync(CREDENTIALS_DIR, { recursive: true, mode: 0o700 });
}
}
/**
* Save credentials to the local file system
*/
export function saveCredentials(credentials: StoredCredentials): void {
ensureCredentialsDir();
fs.writeFileSync(CREDENTIALS_FILE, JSON.stringify(credentials, null, 2), {
mode: 0o600,
});
}
/**
* Load credentials from the local file system
* Returns null if no credentials are stored
*/
export function loadCredentials(): StoredCredentials | null {
if (!fs.existsSync(CREDENTIALS_FILE)) {
return null;
}
try {
const content = fs.readFileSync(CREDENTIALS_FILE, 'utf-8');
return JSON.parse(content) as StoredCredentials;
} catch {
return null;
}
}
/**
* Delete stored credentials
*/
export function deleteCredentials(): void {
if (fs.existsSync(CREDENTIALS_FILE)) {
fs.unlinkSync(CREDENTIALS_FILE);
}
}
/**
* Get the API key from environment variable or stored credentials
* Environment variable takes precedence
*/
export function getApiKey(): string | null {
// Check environment variable first
const envKey = process.env.TESTIVAI_API_KEY;
if (envKey) {
return envKey;
}
// Fall back to stored credentials
const credentials = loadCredentials();
return credentials?.apiKey || null;
}
/**
* Check if the user is authenticated
*/
export function isAuthenticated(): boolean {
return getApiKey() !== null;
}
/**
* Compression utilities for TestivAI SDKs
* Handles gzip compression for upload optimization
*/
import * as zlib from 'zlib';
import { promisify } from 'util';
const gzipAsync = promisify(zlib.gzip);
export interface CompressionOptions {
compressUploads?: boolean;
compressionLevel?: number;
compressionThreshold?: number;
}
export interface CompressionResult {
data: Buffer | string;
headers?: Record<string, string>;
originalSize: number;
compressedSize: number;
compressionRatio: number;
compressionTime: number;
}
export class CompressionHelper {
private options: Required<CompressionOptions>;
constructor(options: CompressionOptions = {}) {
this.options = {
compressUploads: options.compressUploads !== false, // default: true
compressionLevel: options.compressionLevel || 6,
compressionThreshold: options.compressionThreshold || 5 * 1024 * 1024, // 5MB
};
}
/**
* Compress data if it meets the threshold
*/
async compress(data: string): Promise<CompressionResult> {
const originalSize = Buffer.byteLength(data);
const startTime = Date.now();
// Don't compress if disabled or below threshold
if (!this.options.compressUploads || originalSize < this.options.compressionThreshold) {
return {
data,
originalSize,
compressedSize: originalSize,
compressionRatio: 0,
compressionTime: Date.now() - startTime,
};
}
// Compress the data
const compressedData = await gzipAsync(Buffer.from(data), {
level: this.options.compressionLevel
});
const compressionTime = Date.now() - startTime;
const compressionRatio = 1 - compressedData.length / originalSize;
return {
data: compressedData,
headers: {
'Content-Encoding': 'gzip',
'Content-Type': 'application/json',
},
originalSize,
compressedSize: compressedData.length,
compressionRatio,
compressionTime,
};
}
/**
* Format bytes for display
*/
formatBytes(bytes: number): string {
if (bytes < 1024) return bytes + ' B';
if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB';
return (bytes / (1024 * 1024)).toFixed(1) + ' MB';
}
/**
* Log compression result
*/
logCompressionResult(result: CompressionResult): void {
if (result.compressionRatio > 0) {
console.log(
`Testivai Reporter: Compressed batch: ${this.formatBytes(result.originalSize)} → ` +
`${this.formatBytes(result.compressedSize)} (${(result.compressionRatio * 100).toFixed(1)}% reduction, ${result.compressionTime}ms)`
);
}
}
}
export const compressionHelper = new CompressionHelper();
/**
* Configuration loader for TestivAI
* Loads testivai.config.ts from the project root
*/
import * as fs from 'fs';
import * as path from 'path';
import { TestivaiConfig } from './types';
const CONFIG_FILE_NAMES = ['testivai.config.ts', 'testivai.config.js'];
/**
* Default configuration values
*/
export const DEFAULT_CONFIG: TestivaiConfig = {
outputDir: './visual-tests',
viewport: {
width: 1280,
height: 720,
},
};
/**
* Find the config file in the current directory or parent directories
*/
export function findConfigFile(startDir: string = process.cwd()): string | null {
let currentDir = startDir;
while (currentDir !== path.dirname(currentDir)) {
for (const fileName of CONFIG_FILE_NAMES) {
const configPath = path.join(currentDir, fileName);
if (fs.existsSync(configPath)) {
return configPath;
}
}
currentDir = path.dirname(currentDir);
}
return null;
}
/**
* Load configuration from file
* Returns default config if no config file is found
*/
export async function loadConfig(configPath?: string): Promise<TestivaiConfig> {
const resolvedPath = configPath || findConfigFile();
if (!resolvedPath) {
return DEFAULT_CONFIG;
}
try {
// For TypeScript files, we need to use dynamic import
// This requires the project to have ts-node or similar configured
const configModule = await import(resolvedPath);
const userConfig = configModule.default || configModule;
return {
...DEFAULT_CONFIG,
...userConfig,
};
} catch (error) {
console.warn(`Warning: Could not load config from ${resolvedPath}. Using defaults.`);
return DEFAULT_CONFIG;
}
}
/**
* Check if a config file exists in the current directory
*/
export function configExists(dir: string = process.cwd()): boolean {
for (const fileName of CONFIG_FILE_NAMES) {
if (fs.existsSync(path.join(dir, fileName))) {
return true;
}
}
return false;
}
/**
* Get the output directory from config, resolved to absolute path
*/
export function getOutputDir(config: TestivaiConfig, baseDir: string = process.cwd()): string {
const outputDir = config.outputDir || DEFAULT_CONFIG.outputDir!;
return path.isAbsolute(outputDir) ? outputDir : path.join(baseDir, outputDir);
}
/**
* Core API Client for TestivAI
* Handles all HTTP communication with the Core API
*/
import axios, { AxiosInstance, AxiosError } from 'axios';
import { ApiKeyValidationResponse, VisualCheckResult, CaptureData } from './types';
const DEFAULT_API_URL = 'https://core-api.testiv.ai';
export class CoreApiClient {
private client: AxiosInstance;
private apiKey: string;
constructor(apiKey: string, baseUrl?: string) {
this.apiKey = apiKey;
this.client = axios.create({
baseURL: baseUrl || DEFAULT_API_URL,
headers: {
'Content-Type': 'application/json',
'X-API-Key': apiKey,
},
timeout: 30000,
});
}
/**
* Validate an API key against the Core API
*/
async validateApiKey(): Promise<ApiKeyValidationResponse> {
try {
const response = await this.client.get('/api/v1/auth/validate-key');
return {
valid: true,
projectId: response.data.project_id,
projectName: response.data.project_name,
organizationId: response.data.organization_id,
organizationName: response.data.organization_name,
};
} catch (error) {
if (error instanceof AxiosError) {
if (error.response?.status === 401) {
return { valid: false, error: 'Invalid API key' };
}
if (error.response?.status === 403) {
return { valid: false, error: 'API key is disabled or expired' };
}
return { valid: false, error: error.message };
}
return { valid: false, error: 'Unknown error occurred' };
}
}
/**
* Submit a visual check to the Core API
* Note: This method is deprecated and should not be used.
* The correct approach is to use the batch ingest endpoints.
*/
async submitVisualCheck(data: CaptureData): Promise<VisualCheckResult> {
throw new Error(
'submitVisualCheck is deprecated. The /api/v1/visual-check endpoint does not exist. ' +
'Please use the batch ingest flow with /api/v1/ingest/start-batch and /api/v1/ingest/finish-batch endpoints.'
);
}
/**
* Get the status of a test run
*/
async getTestRunStatus(testRunId: string): Promise<VisualCheckResult> {
const response = await this.client.get(`/api/v1/test-runs/${testRunId}`);
return {
testRunId: response.data.id,
status: response.data.status,
hasDiff: response.data.has_diff || response.data.status === 'failed',
diffUrl: response.data.diff_url,
dashboardUrl: response.data.dashboard_url,
pixelsChanged: response.data.pixels_changed,
percentChanged: response.data.percent_changed,
};
}
}
export const DEFAULT_CORE_API_URL = DEFAULT_API_URL;
/**
* @testivai/common
* Shared utilities for TestivAI SDKs and CLI
*/
// Types
export * from './types';
// Core API Client
export { CoreApiClient, DEFAULT_CORE_API_URL } from './core-api-client';
// Authentication
export {
saveCredentials,
loadCredentials,
deleteCredentials,
getApiKey,
isAuthenticated,
} from './auth';
// Configuration
export {
DEFAULT_CONFIG,
findConfigFile,
loadConfig,
configExists,
getOutputDir,
} from './config-loader';
// TestivAI helper for visual checks
export { testivai, witness } from './testivai';
// Compression utilities
export {
CompressionHelper,
compressionHelper,
type CompressionOptions,
type CompressionResult,
} from './compression';
/**
* TestivAI helper for visual regression testing
*
* This is a lightweight wrapper that can be used in generated test scripts.
*
* NOTE: The witness function uses the deprecated submitVisualCheck method.
* For new implementations, use the batch ingest flow instead.
*/
import { CoreApiClient } from './core-api-client';
import { getApiKey } from './auth';
import type { Page } from 'playwright';
/**
* Capture a visual snapshot and submit to TestivAI
*
* This is the main function for capturing visual evidence.
* Aligns with the @testivai/witness-playwright SDK terminology.
*/
export async function witness(page: Page, name: string): Promise<void> {
const apiKey = getApiKey();
if (!apiKey) {
throw new Error('TestivAI API key not found. Run: testivai auth <your-api-key>');
}
// Take screenshot
const screenshot = await page.screenshot({ fullPage: true });
// Get page URL and HTML
const url = page.url();
const html = await page.content();
// Submit to TestivAI
const client = new CoreApiClient(apiKey);
try {
const result = await client.submitVisualCheck({
name,
url,
screenshot,
html,
viewport: page.viewportSize() || { width: 1280, height: 720 },
});
if (result.hasDiff) {
throw new Error(`Visual diff detected for "${name}". View results at: ${result.dashboardUrl || 'https://dashboard.testiv.ai'}`);
}
console.log(`✓ Visual check passed: ${name}`);
} catch (error) {
if (error instanceof Error) {
throw error;
}
throw new Error(`Failed to submit visual check: ${error}`);
}
}
/**
* TestivAI namespace for use in generated scripts
*
* Provides the main witness function for capturing visual evidence.
*/
export const testivai = {
witness,
};
/**
* Shared TypeScript types for TestivAI SDKs and CLI
*/
/**
* TestivAI configuration options
*/
export interface TestivaiConfig {
/** Base URL for visual tests (optional, can be overridden per test) */
baseUrl?: string;
/** Output directory for generated tests */
outputDir?: string;
/** Viewport settings */
viewport?: {
width: number;
height: number;
};
}
/**
* API Key validation response from Core API
*/
export interface ApiKeyValidationResponse {
valid: boolean;
projectId?: string;
projectName?: string;
organizationId?: string;
organizationName?: string;
error?: string;
}
/**
* Credentials stored locally
*/
export interface StoredCredentials {
apiKey: string;
validatedAt: string;
projectId?: string;
projectName?: string;
}
/**
* Visual check result
*/
export interface VisualCheckResult {
testRunId: string;
status: 'passed' | 'failed' | 'new_baseline';
hasDiff: boolean;
diffUrl?: string;
dashboardUrl?: string;
pixelsChanged?: number;
percentChanged?: number;
}
/**
* Capture data sent to Core API
*/
export interface CaptureData {
snapshotName?: string;
name?: string;
url: string;
/**
* Page structure data (raw HTML string)
* @renamed Was `dom` — renamed to conceal internal layer terminology (IP protection)
*/
structure?: string;
html?: string;
layout?: object;
screenshot: Buffer;
viewport: {
width: number;
height: number;
};
metadata?: Record<string, unknown>;
}
/**
* Unified Browser Performance metrics for both Playwright and Witness SDKs
*/
export interface BrowserPerformanceMetrics {
/** Browser runtime metrics */
cdp?: {
Timestamp?: number;
Documents?: number;
Frames?: number;
JSEventListeners?: number;
Nodes?: number;
LayoutCount?: number;
RecalcStyleCount?: number;
LayoutDuration?: number;
RecalcStyleDuration?: number;
ScriptDuration?: number;
TaskDuration?: number;
JSHeapUsedSize?: number;
JSHeapTotalSize?: number;
};
/** Navigation timing and Web Vitals */
timing?: {
navigation?: {
type: number;
redirectCount: number;
};
timing?: {
navigationStart: number;
unloadEventStart: number;
unloadEventEnd: number;
redirectStart: number;
redirectEnd: number;
fetchStart: number;
domainLookupStart: number;
domainLookupEnd: number;
connectStart: number;
connectEnd: number;
secureConnectionStart: number;
requestStart: number;
responseStart: number;
responseEnd: number;
domLoading: number;
domInteractive: number;
domContentLoadedEventStart: number;
domContentLoadedEventEnd: number;
domComplete: number;
loadEventStart: number;
loadEventEnd: number;
};
webVitals?: {
firstContentfulPaint?: number;
largestContentfulPaint?: number;
cumulativeLayoutShift?: number;
firstInputDelay?: number;
};
};
/** Timestamp when metrics were captured */
timestamp?: number;
}
/**
* @deprecated Use BrowserPerformanceMetrics instead
*/
export type CDPerformanceMetrics = BrowserPerformanceMetrics;
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"lib": ["ES2020"],
"declaration": true,
"outDir": "./dist",
"strict": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"moduleResolution": "node",
"types": ["node", "jest"]
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}