@google/clasp
Version:
Develop Apps Script Projects locally
381 lines (380 loc) • 19.7 kB
JavaScript
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var _this = this;
Object.defineProperty(exports, "__esModule", { value: true });
var os = require("os");
var path = require("path");
var chai_1 = require("chai");
var fs = require("fs-extra");
var mocha_1 = require("mocha");
var tmp = require("tmp");
var files_1 = require("./../src/files");
var utils_js_1 = require("./../src/utils.js");
var spawnSync = require('child_process').spawnSync;
var TEST_CODE_JS = 'function test() { Logger.log(\'test\'); }';
var TEST_JSON = '{"timeZone": "America/New_York"}';
var CLASP = (os.type() === 'Windows_NT') ? 'clasp.cmd' : 'clasp';
var isPR = process.env.TRAVIS_PULL_REQUEST;
mocha_1.describe('Test --help for each function', function () {
var expectHelp = function (command, expected) {
var result = spawnSync(CLASP, [command, '--help'], { encoding: 'utf8' });
chai_1.expect(result.status).to.equal(0);
chai_1.expect(result.stdout).to.include(expected);
};
mocha_1.it('should run --help', function () { return expectHelp('run', 'Run a function in your Apps Scripts project'); });
mocha_1.it('should logs --help', function () { return expectHelp('logs', 'Shows the StackDriver logs'); });
mocha_1.it('should login --help', function () { return expectHelp('login', 'Log in to script.google.com'); });
mocha_1.it('should logout --help', function () { return expectHelp('logout', 'Log out'); });
mocha_1.it('should create --help', function () { return expectHelp('create', 'Create a script'); });
mocha_1.it('should clone --help', function () { return expectHelp('clone', 'Clone a project'); });
mocha_1.it('should pull --help', function () { return expectHelp('pull', 'Fetch a remote project'); });
mocha_1.it('should push --help', function () { return expectHelp('push', 'Update the remote project'); });
mocha_1.it('should status --help', function () { return expectHelp('status', 'Lists files that will be pushed by clasp'); });
mocha_1.it('should open --help', function () { return expectHelp('open', 'Open a script'); });
mocha_1.it('should deployments --help', function () { return expectHelp('deployments', 'List deployment ids of a script'); });
mocha_1.it('should undeploy --help', function () { return expectHelp('undeploy', 'Undeploy a deployment of a project'); });
mocha_1.it('should redeploy --help', function () { return expectHelp('redeploy', 'Update a deployment'); });
mocha_1.it('should versions --help', function () { return expectHelp('versions', 'List versions of a script'); });
mocha_1.it('should version --help', function () { return expectHelp('version', 'Creates an immutable version of the script'); });
mocha_1.it('should list --help', function () { return expectHelp('list', 'List App Scripts projects'); });
mocha_1.it('should apis --help', function () { return expectHelp('apis', 'List, enable, or disable apis'); });
mocha_1.it('should help --help', function () { return expectHelp('help', 'Display help'); });
});
mocha_1.describe('Test clasp list function', function () {
before(function () {
if (isPR !== 'false') {
this.skip();
}
});
mocha_1.it('should list clasp projects correctly', function () {
var result = spawnSync(CLASP, ['list'], { encoding: 'utf8' });
// Every project starts with this base URL, thus
// using clasp list should at least contain this
// in its output.
chai_1.expect(result.stdout).to.contain('https://script.google.com/d/');
chai_1.expect(result.status).to.equal(0);
});
});
mocha_1.describe('Test clasp create function', function () {
before(function () {
if (isPR !== 'false') {
this.skip();
}
});
mocha_1.it('should prompt for a project name correctly', function () {
spawnSync('rm', ['.clasp.json']);
var result = spawnSync(CLASP, ['create'], { encoding: 'utf8' });
chai_1.expect(result.stdout).to.contain('Give a script title:');
});
mocha_1.it('should not prompt for project name', function () {
fs.writeFileSync('.clasp.json', '');
var result = spawnSync(CLASP, ['create'], { encoding: 'utf8' });
chai_1.expect(result.stderr).to.contain('Project file (.clasp.json) already exists.');
});
});
mocha_1.describe('Test clasp create <title> function', function () {
before(function () {
if (isPR !== 'false') {
this.skip();
}
});
mocha_1.it('should create a new project named <title> correctly', function () {
spawnSync('rm', ['.clasp.json']);
var result = spawnSync(CLASP, ['create', 'myTitle'], { encoding: 'utf8' });
chai_1.expect(result.stdout).to.contain('Created new script: https://script.google.com/d/');
chai_1.expect(result.status).to.equal(0);
});
});
mocha_1.describe('Test clasp clone <scriptId> function', function () {
before(function () {
if (isPR !== 'false') {
this.skip();
}
});
mocha_1.it('should clone an existing project correctly', function () {
var settings = JSON.parse(fs.readFileSync('.clasp.json', 'utf8'));
fs.removeSync('.clasp.json');
var result = spawnSync(CLASP, ['clone', settings.scriptId], { encoding: 'utf8' });
chai_1.expect(result.stdout).to.contain('Cloned');
chai_1.expect(result.stdout).to.contain('files.');
chai_1.expect(result.status).to.equal(0);
});
mocha_1.it('should give an error on a non-existing project', function () {
var settings = JSON.parse(fs.readFileSync('.clasp.json', 'utf8'));
fs.removeSync('.clasp.json');
var result = spawnSync(CLASP, ['clone', 'non-existing-project'], { encoding: 'utf8' });
chai_1.expect(result.stderr).to.contain('> Did you provide the correct scriptId?');
chai_1.expect(result.status).to.equal(1);
fs.writeFileSync('.clasp.json', JSON.stringify(settings));
});
});
mocha_1.describe('Test clasp pull function', function () {
before(function () {
if (isPR !== 'false') {
this.skip();
}
});
mocha_1.it('should pull an existing project correctly', function () {
var result = spawnSync(CLASP, ['pull'], { encoding: 'utf8' });
chai_1.expect(result.stdout).to.contain('Cloned');
chai_1.expect(result.stdout).to.contain('files.');
chai_1.expect(result.status).to.equal(0);
});
});
mocha_1.describe('Test clasp push function', function () {
before(function () {
if (isPR !== 'false') {
this.skip();
}
});
mocha_1.it('should push local project correctly', function () {
fs.removeSync('.claspignore');
fs.writeFileSync('Code.js', TEST_CODE_JS);
fs.writeFileSync('appsscript.json', TEST_JSON);
fs.writeFileSync('.claspignore', '**/**\n!Code.js\n!appsscript.json');
var result = spawnSync(CLASP, ['push'], { encoding: 'utf8' });
chai_1.expect(result.stdout).to.contain('Pushed');
chai_1.expect(result.stdout).to.contain('files.');
chai_1.expect(result.status).to.equal(0);
});
mocha_1.it('should return non-0 exit code when push failed', function () {
fs.writeFileSync('.claspignore', '**/**\n!Code.js\n!appsscript.json\n!unexpected_file');
fs.writeFileSync('unexpected_file', TEST_CODE_JS);
var result = spawnSync(CLASP, ['push'], { encoding: 'utf8' });
chai_1.expect(result.stderr).to.contain('Invalid value at');
chai_1.expect(result.stderr).to.contain('UNEXPECTED_FILE');
chai_1.expect(result.stderr).to.contain('Files to push were:');
chai_1.expect(result.status).to.equal(1);
});
});
mocha_1.describe('Test clasp status function', function () {
before(function () {
if (isPR !== 'false') {
this.skip();
}
});
function setupTmpDirectory(filepathsAndContents) {
fs.ensureDirSync('tmp');
var tmpdir = tmp.dirSync({ unsafeCleanup: true, dir: 'tmp/', keep: false }).name;
filepathsAndContents.forEach(function (_a) {
var file = _a.file, data = _a.data;
fs.outputFileSync(path.join(tmpdir, file), data);
});
return tmpdir;
}
mocha_1.it('should respect globs and negation rules', function () {
var tmpdir = setupTmpDirectory([
{ file: '.claspignore', data: '**/**\n!build/main.js\n!appsscript.json' },
{ file: 'build/main.js', data: TEST_CODE_JS },
{ file: 'appsscript.json', data: TEST_JSON },
{ file: 'shouldBeIgnored', data: TEST_CODE_JS },
{ file: 'should/alsoBeIgnored', data: TEST_CODE_JS },
]);
spawnSync(CLASP, ['create', '[TEST] clasp status'], { encoding: 'utf8', cwd: tmpdir });
var result = spawnSync(CLASP, ['status', '--json'], { encoding: 'utf8', cwd: tmpdir });
chai_1.expect(result.status).to.equal(0);
var resultJson = JSON.parse(result.stdout);
chai_1.expect(resultJson.untrackedFiles).to.have.members(['shouldBeIgnored', 'should/alsoBeIgnored']);
chai_1.expect(resultJson.filesToPush).to.have.members(['build/main.js', 'appsscript.json']);
});
// https://github.com/google/clasp/issues/67 - This test currently fails
mocha_1.it.skip('should ignore dotfiles if the parent folder is ignored', function () {
var tmpdir = setupTmpDirectory([
{ file: '.claspignore', data: '**/node_modules/**\n**/**\n!appsscript.json' },
{ file: 'appsscript.json', data: TEST_JSON },
{ file: 'node_modules/fsevents/build/Release/.deps/Release/.node.d', data: TEST_CODE_JS },
]);
spawnSync(CLASP, ['create', '[TEST] clasp status'], { encoding: 'utf8', cwd: tmpdir });
var result = spawnSync(CLASP, ['status', '--json'], { encoding: 'utf8', cwd: tmpdir });
chai_1.expect(result.status).to.equal(0);
var resultJson = JSON.parse(result.stdout);
chai_1.expect(resultJson.untrackedFiles).to.have.members([
'node_modules/fsevents/build/Release/.deps/Release/.node.d'
]);
chai_1.expect(resultJson.filesToPush).to.have.members(['appsscript.json']);
});
});
mocha_1.describe('Test clasp open function', function () {
before(function () {
if (isPR !== 'false') {
this.skip();
}
});
mocha_1.it('should open a project correctly', function () {
var result = spawnSync(CLASP, ['open'], { encoding: 'utf8' });
//should open a browser with the project
chai_1.expect(result.status).to.equal(0);
});
});
mocha_1.describe('Test clasp deployments function', function () {
before(function () {
if (isPR !== 'false') {
this.skip();
}
});
mocha_1.it('should list deployments correctly', function () {
var result = spawnSync(CLASP, ['deployments'], { encoding: 'utf8' });
chai_1.expect(result.stdout).to.contain('Deployment');
chai_1.expect(result.status).to.equal(0);
});
});
mocha_1.describe('Test clasp deploy function', function () {
before(function () {
if (isPR !== 'false') {
this.skip();
}
});
mocha_1.it('should deploy correctly', function () {
var result = spawnSync(CLASP, ['deploy'], { encoding: 'utf8' });
chai_1.expect(result.stdout).to.contain('Created version ');
chai_1.expect(result.status).to.equal(0);
});
});
mocha_1.describe('Test clasp version and versions function', function () {
before(function () {
if (isPR !== 'false') {
this.skip();
}
});
var versionNumber = '';
mocha_1.it('should create new version correctly', function () {
var result = spawnSync(CLASP, ['version'], { encoding: 'utf8' });
chai_1.expect(result.stdout).to.contain('Created version ');
chai_1.expect(result.status).to.equal(0);
versionNumber = result.stdout.substring(result.stdout.lastIndexOf(' '), result.stdout.length - 2);
mocha_1.it('should list versions correctly', function () {
var result = spawnSync(CLASP, ['versions'], { encoding: 'utf8' });
chai_1.expect(result.stdout).to.contain('Versions');
chai_1.expect(result.stdout).to.contain(versionNumber + ' - ');
chai_1.expect(result.status).to.equal(0);
});
});
});
mocha_1.describe('Test clasp clone function', function () {
before(function () {
if (isPR !== 'false') {
this.skip();
}
});
mocha_1.it('should prompt for which script to clone correctly', function () {
spawnSync('rm', ['.clasp.json']);
var result = spawnSync(CLASP, ['clone'], { encoding: 'utf8' });
chai_1.expect(result.stdout).to.contain('Clone which script?');
});
mocha_1.it('should give an error if .clasp.json already exists', function () {
fs.writeFileSync('.clasp.json', '');
var result = spawnSync(CLASP, ['clone'], { encoding: 'utf8' });
chai_1.expect(result.stderr).to.contain('Project file (.clasp.json) already exists.');
chai_1.expect(result.status).to.equal(1);
});
});
mocha_1.describe('Test getScriptURL function from utils', function () {
mocha_1.it('should return the scriptURL correctly', function () {
var url = utils_js_1.getScriptURL('abcdefghijklmnopqrstuvwxyz');
chai_1.expect(url).to.equal('https://script.google.com/d/abcdefghijklmnopqrstuvwxyz/edit');
});
});
mocha_1.describe('Test getFileType function from utils', function () {
mocha_1.it('should return the lowercase file type correctly', function () {
chai_1.expect(files_1.getFileType('SERVER_JS')).to.equal('js');
chai_1.expect(files_1.getFileType('GS')).to.equal('gs');
chai_1.expect(files_1.getFileType('JS')).to.equal('js');
});
});
mocha_1.describe('Test getAPIFileType function from utils', function () {
mocha_1.it('should return the uppercase file type correctly', function () {
chai_1.expect(utils_js_1.getAPIFileType('file.GS')).to.equal('SERVER_JS');
chai_1.expect(utils_js_1.getAPIFileType('file.JS')).to.equal('SERVER_JS');
chai_1.expect(utils_js_1.getAPIFileType('file.js')).to.equal('SERVER_JS');
chai_1.expect(utils_js_1.getAPIFileType('file.jsx')).to.equal('JSX');
chai_1.expect(utils_js_1.getAPIFileType('file.js.html')).to.equal('HTML');
});
});
mocha_1.describe('Test saveProjectId function from utils', function () {
mocha_1.it('should save the scriptId correctly', function () {
spawnSync('rm', ['.clasp.json']);
var isSaved = function () { return __awaiter(_this, void 0, void 0, function () {
var id;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, utils_js_1.saveProjectId('12345')];
case 1:
_a.sent();
id = fs.readFileSync(path.join(__dirname, '/../.clasp.json'), 'utf8');
chai_1.expect(id).to.equal('{"scriptId":"12345"}');
return [2 /*return*/];
}
});
}); };
chai_1.expect(isSaved).to.not.equal(null);
});
});
mocha_1.describe('Test clasp apis functions', function () {
mocha_1.it('should list apis correctly', function () {
var result = spawnSync('clasp', ['apis', 'list'], { encoding: 'utf8' });
chai_1.expect(result.status).to.equal(0);
chai_1.expect(result.stdout).to.contain('abusiveexperiencereport - abusiveexperiencereport:v1');
chai_1.expect(result.stdout).to.contain('youtubereporting - youtubereporting:v1');
});
mocha_1.it('should enable apis correctly', function () {
var result = spawnSync('clasp', ['apis', 'enable'], { encoding: 'utf8' });
chai_1.expect(result.status).to.equal(0);
chai_1.expect(result.stdout).to.contain('In development...');
});
mocha_1.it('should disable apis correctly', function () {
var result = spawnSync('clasp', ['apis', 'disable'], { encoding: 'utf8' });
chai_1.expect(result.status).to.equal(0);
chai_1.expect(result.stdout).to.contain('In development...');
});
mocha_1.it('should error with unknown subcommand', function () {
var result = spawnSync('clasp', ['apis', 'unknown'], { encoding: 'utf8' });
chai_1.expect(result.status).to.equal(1);
chai_1.expect(result.stderr).to.contain('Unknown command "apis unknown"');
});
});
mocha_1.describe('Test clasp logout function', function () {
mocha_1.it('should logout correctly', function () {
fs.writeFileSync('.clasprc.json', TEST_JSON);
fs.writeFileSync(path.join(os.homedir(), '/.clasprc.json'), TEST_JSON);
var result = spawnSync(CLASP, ['logout'], { encoding: 'utf8' });
chai_1.expect(result.status).to.equal(0);
var localDotExists = fs.existsSync('.clasprc.json');
chai_1.expect(localDotExists).to.equal(false);
var dotExists = fs.existsSync('~/.clasprc.json');
chai_1.expect(dotExists).to.equal(false);
});
});
;