import BundlesClient from "@staticdeploy/sdk/lib/BundlesClient" ; import tarArchiver from "@staticdeploy/tar-archiver" ; import { expect } from "chai" ; import { createTree , destroyTree } from "create-fs-tree" ; import { emptyDirSync , removeSync } from "fs-extra" ; import { tmpdir } from "os" ; import { join } from "path" ; import sinon from "sinon" ; import yargs from "yargs" ; import bundle from "../../src/commands/bundle" ; describe ( "bundle command" , ( ) => { const baseTestPath = join ( tmpdir ( ) , "staticdeploy-cli" ) ; before ( ( ) => { emptyDirSync ( baseTestPath ) ; } ) ; describe ( "config" , ( ) => { const workdir = join ( baseTestPath , "bundle-workdir" ) ; before ( ( ) => { createTree ( workdir , { "staticdeploy.config.js" : `module.exports = {
                    "bundle": {
                        apiUrl: "staticdeploy.config.js apiUrl",
                        apiToken: "apiToken",
                        from: "from",
                        name: "name",
                        tag: "tag",
                        description: "description",
                        fallbackAssetPath: "/fallbackAssetPath",
                        fallbackStatusCode: 200,
                        headers: {
                            "assetMatcher": {
                                "headerName": "headerValue"
                            }
                        }
                    }
                };` , } ) ; } ) ; after ( ( ) => { destroyTree ( workdir ) ; } ) ; const handler = sinon . spy ( ) ; const argv = yargs ( [ ] , workdir ) . command ( { ... bundle , handler } ) . demandCommand ( 1 ) . exitProcess ( false ) . strict ( ) ; beforeEach ( ( ) => { handler . resetHistory ( ) ; } ) ; const ignoreParseErrors = ( ) => null ; describe ( "reads options from a config file or from command line flags" , ( ) => { it ( "case: config file" , ( ) => { argv . parse ( `bundle --config ${ workdir }/staticdeploy.config.js` , ignoreParseErrors ) ; expect ( handler ) . to . have . callCount ( 1 ) ; expect ( handler ) . to . have . been . calledWithMatch ( { apiUrl : "staticdeploy.config.js apiUrl" , } ) ; } ) ; it ( "case: command line flags" , ( ) => { argv . parse ( "bundle --config non-existing --apiUrl apiUrl --apiToken apiToken --from from --name name --tag tag --description description" , ignoreParseErrors ) ; expect ( handler ) . to . have . callCount ( 1 ) ; expect ( handler ) . to . have . been . calledWithMatch ( { apiUrl : "apiUrl" , } ) ; } ) ; it ( "case: config file and command line flags" , ( ) => { argv . parse ( `bundle --config ${ workdir }/staticdeploy.config.js --apiUrl apiUrl` ) ; expect ( handler ) . to . have . callCount ( 1 ) ; expect ( handler ) . to . have . been . calledWithMatch ( { apiUrl : "apiUrl" , } ) ; } ) ; } ) ; } ) ; describe ( "handler" , ( ) => { const unpackingFolder = join ( baseTestPath , "unpacking-folder" ) ; const targetTree = join ( baseTestPath , "target-tree" ) ; beforeEach ( ( ) => { createTree ( targetTree , { target : { "index.html" : "index.html" , js : { "index.js" : "index.js" , } , } , "not-a-directory" : "not-a-directory" , } ) ; emptyDirSync ( unpackingFolder ) ; } ) ; after ( ( ) => { removeSync ( unpackingFolder ) ; destroyTree ( targetTree ) ; } ) ; const commonOptions = { apiUrl : "apiUrl" , apiToken : "apiToken" , name : "name" , tag : "tag" , description : "description" , fallbackAssetPath : "/index.html" , fallbackStatusCode : 200 , headers : "{}" , } ; let bundlesCreateStub ; beforeEach ( ( ) => { bundlesCreateStub = sinon . stub ( BundlesClient . prototype , "create" ) ; } ) ; afterEach ( ( ) => { bundlesCreateStub . restore ( ) ; } ) ; it ( "throws an error if the target path is empty" , async ( ) => { const createPromise = bundle . handler ( { ... commonOptions , from : join ( targetTree , "path-to-nothing" ) , } ) ; await expect ( createPromise ) . to . be . rejectedWith ( /No directory found at/ ) ; } ) ; it ( "throws error if the target path is not a directory" , async ( ) => { const createPromise = bundle . handler ( { ... commonOptions , from : join ( targetTree , "not-a-directory" ) , } ) ; await expect ( createPromise ) . to . be . rejectedWith ( /No directory found at/ ) ; } ) ; it ( "throws error if there is no file corresponding to the specified fallbackAssetPath" , async ( ) => { const createPromise = bundle . handler ( { ... commonOptions , from : join ( targetTree , "target" ) , fallbackAssetPath : "/non-existing" , } ) ; await expect ( createPromise ) . to . be . rejectedWith ( /\/non-existing cannot be set as fallbackAssetPath/ ) ; } ) ; it ( "packages the target path into a tar archive" , async ( ) => { await bundle . handler ( { ... commonOptions , from : join ( targetTree , "target" ) , } ) ; const { content } = bundlesCreateStub . getCall ( 0 ) . args [ 0 ] ; const files = await tarArchiver . extractFiles ( Buffer . from ( content , "base64" ) ) ; expect ( files ) . to . deep . equalInAnyOrder ( [ { path : "/index.html" , content : Buffer . from ( "index.html" ) } , { path : "/js/index.js" , content : Buffer . from ( "index.js" ) } , ] ) ; } ) ; it ( "creates a bundle" , async ( ) => { await bundle . handler ( { ... commonOptions , from : join ( targetTree , "target" ) , } ) ; expect ( bundlesCreateStub ) . to . have . callCount ( 1 ) ; expect ( bundlesCreateStub ) . to . have . been . calledWithMatch ( { content : sinon . match . string , name : "name" , tag : "tag" , description : "description" , fallbackAssetPath : "/index.html" , fallbackStatusCode : 200 , headers : { } , } ) ; } ) ; } ) ; } ) ;