Best JavaScript code snippet using jest
cli-test.js
Source:cli-test.js
1const { expect } = require('chai');2const { shellCommand } = require("../utils/async");3const fs = require('fs');4const glob = require('fast-glob');5const Git = require('isomorphic-git');6const { resolve } = require('path');7const crypto2 = require('crypto2');8const { cli, setupFixtureRepo, setupBareFixtureRepo } = require('./helper');9const { TestHelper } = require('zos');10const { Contracts, ZWeb3 } = require('zos-lib');11ZWeb3.initialize(web3.currentProvider);12const GithereumContract = Contracts.getFromLocal('Githereum');13contract("Githereum", (addresses) => {14 const [ owner, repoOwner, someRandomAddress, otherOwner, ownerOfOtherRepo, writer, otherWriter, reader, otherReader ] = addresses;15 let githereumContract;16 async function runCli(cmd) {17 return await cli(`${githereumContract.address} ${cmd}`);18 }19 async function getHead(repoAndTag) {20 let headOutput = await runCli(`head ${repoAndTag}`);21 let head = headOutput.match(/ is ([0-9a-fA-F]+)/)[1];22 return head;23 }24 async function getRepo(name) {25 return await githereumContract.methods.repos(name).call();26 }27 async function ownerCount(name) {28 let repo = await getRepo(name);29 return Number(repo.ownerCount);30 }31 beforeEach(async () => {32 await shellCommand("rm -rf tmp");33 await shellCommand("mkdir tmp");34 this.project = await TestHelper();35 githereumContract = await this.project.createProxy(GithereumContract);36 });37 describe("Roles", async function() {38 this.slow(1000);39 it("Registers a repo", async function() {40 await runCli(`register my-great-repo --from ${repoOwner}`);41 expect(await githereumContract.methods.isOwner("my-great-repo", repoOwner).call()).to.be.ok;42 expect(await githereumContract.methods.isOwner("my-great-repo", owner).call()).to.not.be.ok;43 expect(await githereumContract.methods.isOwner("my-great-repo", someRandomAddress).call()).to.not.be.ok;44 expect(await githereumContract.methods.isPublic("my-great-repo").call()).to.be.ok;45 expect(await githereumContract.methods.isPrivate("my-great-repo").call()).to.not.be.ok;46 expect(await ownerCount('my-great-repo')).to.equal(1);47 });48 it("Doesn't allow registering an existing repo", async function() {49 await runCli(`register my-great-repo --from ${repoOwner}`);50 expect(await githereumContract.methods.isOwner("my-great-repo", repoOwner).call()).to.be.ok;51 let attemptedCreate = runCli(`register my-great-repo --from ${repoOwner}`);52 await expect(attemptedCreate).to.be.rejectedWith(/Repo already exists/);53 });54 it("Repo owners can add new repo owners to a repo", async function() {55 await runCli(`register my-great-repo --from ${repoOwner}`);56 expect(await githereumContract.methods.isOwner("my-great-repo", otherOwner).call()).to.not.be.ok;57 await runCli(`add owner my-great-repo ${otherOwner} --from ${repoOwner}`);58 expect(await githereumContract.methods.isOwner("my-great-repo", repoOwner).call()).to.be.ok;59 expect(await githereumContract.methods.isOwner("my-great-repo", otherOwner).call()).to.be.ok;60 expect(await ownerCount('my-great-repo')).to.equal(2);61 });62 it("Repo owners cannot add new repo owners to a repo they do not own", async function() {63 await runCli(`register my-great-repo --from ${repoOwner}`);64 await runCli(`register other-repo --from ${ownerOfOtherRepo}`);65 expect(await githereumContract.methods.isOwner("my-great-repo", ownerOfOtherRepo).call()).to.not.be.ok;66 expect(await githereumContract.methods.isOwner("my-great-repo", someRandomAddress).call()).to.not.be.ok;67 expect(await ownerCount('my-great-repo')).to.equal(1);68 let attemptedAdd = runCli(`add owner my-great-repo ${someRandomAddress} --from ${ownerOfOtherRepo}`);69 await expect(attemptedAdd).to.be.rejectedWith(/Only repo owners can add new owners/);70 expect(await githereumContract.methods.isOwner("my-great-repo", ownerOfOtherRepo).call()).to.not.be.ok;71 expect(await githereumContract.methods.isOwner("my-great-repo", someRandomAddress).call()).to.not.be.ok;72 expect(await ownerCount('my-great-repo')).to.equal(1);73 });74 it("Repo owners can remove existing repo owners from a repo", async function() {75 await runCli(`register my-great-repo --from ${repoOwner}`);76 await runCli(`add owner my-great-repo ${otherOwner} --from ${repoOwner}`);77 expect(await ownerCount('my-great-repo')).to.equal(2);78 expect(await githereumContract.methods.isOwner("my-great-repo", repoOwner).call()).to.be.ok;79 expect(await githereumContract.methods.isOwner("my-great-repo", otherOwner).call()).to.be.ok;80 await runCli(`remove owner my-great-repo ${repoOwner} --from ${otherOwner}`);81 expect(await githereumContract.methods.isOwner("my-great-repo", repoOwner).call()).to.not.be.ok;82 expect(await githereumContract.methods.isOwner("my-great-repo", otherOwner).call()).to.be.ok;83 expect(await ownerCount('my-great-repo')).to.equal(1);84 });85 it("Repo owners cannot remove existing repo owners from a repo they do not own", async function() {86 await runCli(`register my-great-repo --from ${repoOwner}`);87 await runCli(`add owner my-great-repo ${otherOwner} --from ${repoOwner}`);88 await runCli(`register other-repo --from ${ownerOfOtherRepo}`);89 expect(await ownerCount('my-great-repo')).to.equal(2);90 expect(await githereumContract.methods.isOwner("my-great-repo", repoOwner).call()).to.be.ok;91 expect(await githereumContract.methods.isOwner("my-great-repo", otherOwner).call()).to.be.ok;92 expect(await githereumContract.methods.isOwner("my-great-repo", ownerOfOtherRepo).call()).to.not.be.ok;93 let attemptedRemove = runCli(`remove owner my-great-repo ${repoOwner} --from ${ownerOfOtherRepo}`);94 await expect(attemptedRemove).to.be.rejectedWith(/Only repo owners can remove owners/);95 expect(await ownerCount('my-great-repo')).to.equal(2);96 });97 it("Last owner cannot be removed from a repo", async function() {98 await runCli(`register my-great-repo --from ${repoOwner}`);99 let attemptedRemove = runCli(`remove owner my-great-repo ${repoOwner} --from ${repoOwner}`);100 await expect(attemptedRemove).to.be.rejectedWith(/Cannot remove the last owner from a repo/);101 });102 it("Repo owners can write to a repo they own", async function() {103 await runCli(`register my-great-repo --from ${repoOwner}`);104 await setupFixtureRepo('dummygit');105 await runCli(`push tmp/dummygit my-great-repo:my-tag --from ${repoOwner}`);106 });107 it("Repo owners can add writers to a repo", async function() {108 await runCli(`register my-great-repo --from ${repoOwner}`);109 expect(await githereumContract.methods.isWriter("my-great-repo", writer).call()).to.not.ok;110 await runCli(`add writer my-great-repo ${writer} --from ${repoOwner}`);111 expect(await githereumContract.methods.isWriter("my-great-repo", writer).call()).to.be.ok;112 });113 it("Repo owners cannot add writers to a repo they do not own", async function() {114 await runCli(`register my-great-repo --from ${repoOwner}`);115 await runCli(`register other-repo --from ${otherOwner}`);116 expect(await githereumContract.methods.isWriter("my-great-repo", writer).call()).to.not.ok;117 let attemptedAdd = runCli(`add writer my-great-repo ${writer} --from ${otherOwner}`);118 await expect(attemptedAdd).to.be.rejectedWith(/Only repo owners can add new writers/);119 expect(await githereumContract.methods.isWriter("my-great-repo", writer).call()).to.not.ok;120 });121 it("Writers can write to a repo they are writers of", async function() {122 await runCli(`register my-great-repo --from ${repoOwner}`);123 await runCli(`add writer my-great-repo ${writer} --from ${repoOwner}`);124 await setupFixtureRepo('dummygit');125 await runCli(`push tmp/dummygit my-great-repo:my-tag --from ${writer}`);126 });127 it("Writers cannot write to a repo they are not writers of", async function() {128 await runCli(`register my-great-repo --from ${repoOwner}`);129 await runCli(`register other-repo --from ${otherOwner}`);130 await runCli(`add writer other-repo ${writer} --from ${otherOwner}`);131 await setupFixtureRepo('dummygit');132 let attemptedPush = runCli(`push tmp/dummygit my-great-repo:my-tag --from ${writer}`);133 await expect(attemptedPush).to.be.rejectedWith(/Cannot push to a repo that you are not a writer or owner of/);134 });135 it("Writers cannot add repo owners to a repo", async function() {136 await runCli(`register my-great-repo --from ${repoOwner}`);137 await runCli(`add writer my-great-repo ${writer} --from ${repoOwner}`);138 let attemptedAdd = runCli(`add owner my-great-repo ${someRandomAddress} --from ${writer}`);139 await expect(attemptedAdd).to.be.rejectedWith(/Only repo owners can add new owners/);140 });141 it("Writers cannot add writers to a repo", async function() {142 await runCli(`register my-great-repo --from ${repoOwner}`);143 await runCli(`add writer my-great-repo ${writer} --from ${repoOwner}`);144 let attemptedAdd = runCli(`add writer my-great-repo ${someRandomAddress} --from ${writer}`);145 await expect(attemptedAdd).to.be.rejectedWith(/Only repo owners can add new writers/);146 });147 it("Writers cannot remove repo owners from a repo", async function() {148 await runCli(`register my-great-repo --from ${repoOwner}`);149 await runCli(`add owner my-great-repo ${otherOwner} --from ${repoOwner}`);150 await runCli(`add writer my-great-repo ${writer} --from ${repoOwner}`);151 let attemptedRemove = runCli(`remove owner my-great-repo ${repoOwner} --from ${writer}`);152 await expect(attemptedRemove).to.be.rejectedWith(/Only repo owners can remove owners/);153 });154 it("Writers cannot remove writers from a repo", async function() {155 await runCli(`register my-great-repo --from ${repoOwner}`);156 await runCli(`add writer my-great-repo ${writer} --from ${repoOwner}`);157 await runCli(`add writer my-great-repo ${otherWriter} --from ${repoOwner}`);158 let attemptedRemove = runCli(`remove writer my-great-repo ${otherWriter} --from ${writer}`);159 await expect(attemptedRemove).to.be.rejectedWith(/Only repo owners can remove writers/);160 });161 it("Cannot write to a repo that is not registered", async function() {162 await setupFixtureRepo('dummygit');163 let attemptedPush = runCli(`push tmp/dummygit my-great-repo:my-tag --from ${writer}`);164 await expect(attemptedPush).to.be.rejectedWith(/my-great-repo is not registered/);165 });166 it("Repo owners cannot write to a repo they do not own", async function() {167 await runCli(`register my-great-repo --from ${repoOwner}`);168 await runCli(`register other-repo --from ${ownerOfOtherRepo}`);169 await setupFixtureRepo('dummygit');170 let attemptedPush = runCli(`push tmp/dummygit my-great-repo:my-tag --from ${ownerOfOtherRepo}`);171 await expect(attemptedPush).to.be.rejectedWith(/Cannot push to a repo that you are not a writer or owner of/);172 });173 it("Cannot read from a repo that is not registered", async function() {174 let attemptedHead = runCli(`head some-repo:master`);175 await expect(attemptedHead).to.be.rejectedWith(/Repo is not registered/);176 let attemptedClone = runCli(`clone some-repo:master tmp/repo`);177 await expect(attemptedClone).to.be.rejectedWith(/some-repo is not registered/);178 let attemptedPull = runCli(`pull some-repo:master tmp/repo`);179 await expect(attemptedPull).to.be.rejectedWith(/some-repo is not registered/);180 });181 it("Cannot register a repo with : in the name", async function() {182 let attemptedRegister = runCli(`register repo:badname --from ${repoOwner}`);183 await expect(attemptedRegister).to.be.rejectedWith(/Repo names cannot contain the : character/);184 });185 it("Anyone can read from a repo", async function() {186 await setupFixtureRepo('dummygit');187 await runCli(`register my-repo --from ${repoOwner}`);188 await runCli(`push tmp/dummygit my-repo:my-tag --from ${repoOwner}`);189 await runCli(`head my-repo:my-tag`);190 await runCli(`clone my-repo:my-tag tmp/cloned`);191 await runCli(`pull my-repo:my-tag tmp/cloned`);192 });193 });194 describe("Private Repos", async function() {195 before(async function() {196 await shellCommand("rm -rf testkeys");197 await cli(`keygen testkeys/owner`);198 await cli(`keygen testkeys/otherowner`);199 await cli(`keygen testkeys/writer`);200 await cli(`keygen testkeys/reader`);201 });202 after(async function() {203 await shellCommand("rm -rf testkeys");204 });205 this.slow(4000);206 it("Generates an rsa keypair", async function() {207 await cli(`keygen tmp/mykeypair`);208 expect(fs.readFileSync(resolve('tmp', 'mykeypair', 'rsa.pub'), 'utf8')).to.match(/BEGIN PUBLIC KEY/);209 expect(fs.readFileSync(resolve('tmp', 'mykeypair', 'rsa.pem'), 'utf8')).to.match(/BEGIN RSA PRIVATE KEY/);210 });211 it("Registers a private repo", async function() {212 await runCli(`register my-great-repo --private testkeys/owner --from ${repoOwner}`);213 expect(await githereumContract.methods.isOwner("my-great-repo", repoOwner).call()).to.be.ok;214 expect(await githereumContract.methods.isOwner("my-great-repo", owner).call()).to.not.be.ok;215 expect(await githereumContract.methods.isOwner("my-great-repo", someRandomAddress).call()).to.not.be.ok;216 expect(await githereumContract.methods.isPrivate("my-great-repo").call()).to.be.ok;217 expect(await githereumContract.methods.isPublic("my-great-repo").call()).to.not.be.ok;218 let publicKey = fs.readFileSync('testkeys/owner/rsa.pub', 'utf8');219 expect(await githereumContract.methods.publicKey("my-great-repo", repoOwner).call()).to.equal(publicKey);220 expect(await ownerCount('my-great-repo')).to.equal(1);221 });222 it("Repo owners can add new repo owners to a private repo", async function() {223 await runCli(`register my-great-repo --private testkeys/owner --from ${repoOwner}`);224 let key = await githereumContract.methods.encryptedKey("my-great-repo", repoOwner).call();225 expect(await githereumContract.methods.isOwner("my-great-repo", otherOwner).call()).to.not.be.ok;226 expect(await githereumContract.methods.encryptedKey("my-great-repo", repoOwner).call()).to.equal(key);227 await runCli(`add owner my-great-repo ${otherOwner} --private testkeys/owner --public testkeys/otherowner --from ${repoOwner}`);228 expect(await githereumContract.methods.encryptedKey("my-great-repo", repoOwner).call()).to.equal(key);229 expect(await githereumContract.methods.isOwner("my-great-repo", repoOwner).call()).to.be.ok;230 expect(await githereumContract.methods.isOwner("my-great-repo", otherOwner).call()).to.be.ok;231 expect(await ownerCount('my-great-repo')).to.equal(2);232 // Can decrypt symmetric key233 let newOwnerPrivateKey = await crypto2.readPrivateKey('testkeys/otherowner/rsa.pem');234 let ownerPrivateKey = await crypto2.readPrivateKey('testkeys/owner/rsa.pem');235 let ownerEncryptedKey = await githereumContract.methods.encryptedKey("my-great-repo", repoOwner).call();236 let newOwnerEncryptedKey = await githereumContract.methods.encryptedKey("my-great-repo", otherOwner).call();237 let newOwnerDecryptedKey = await crypto2.decrypt.rsa(newOwnerEncryptedKey, newOwnerPrivateKey);238 let ownerDecryptedKey = await crypto2.decrypt.rsa(ownerEncryptedKey, ownerPrivateKey);239 expect(ownerDecryptedKey).to.equal(newOwnerDecryptedKey, "The symmetric keys should be the same after decrypting with the associated private key");240 });241 it("Requires key to add owner", async function() {242 await runCli(`register my-great-repo --private testkeys/owner --from ${repoOwner}`);243 expect(await githereumContract.methods.isOwner("my-great-repo", otherOwner).call()).to.not.be.ok;244 let attemptedAdd = runCli(`add owner my-great-repo ${otherOwner} --from ${repoOwner}`);245 await expect(attemptedAdd).to.be.rejectedWith(/Public and private key is required to add owner to private repo/);246 });247 it("Repo owners can add writers to a private repo", async function() {248 await runCli(`register my-great-repo --private testkeys/owner --from ${repoOwner}`);249 expect(await githereumContract.methods.isWriter("my-great-repo", writer).call()).to.not.ok;250 await runCli(`add writer my-great-repo ${writer} --private testkeys/owner --public testkeys/writer --from ${repoOwner}`);251 expect(await githereumContract.methods.isWriter("my-great-repo", writer).call()).to.be.ok;252 // Can decrypt symmetric key253 let writerPrivateKey = await crypto2.readPrivateKey('testkeys/writer/rsa.pem');254 let ownerPrivateKey = await crypto2.readPrivateKey('testkeys/owner/rsa.pem');255 let ownerEncryptedKey = await githereumContract.methods.encryptedKey("my-great-repo", repoOwner).call();256 let writerEncryptedKey = await githereumContract.methods.encryptedKey("my-great-repo", writer).call();257 let writerDecryptedKey = await crypto2.decrypt.rsa(writerEncryptedKey, writerPrivateKey);258 let ownerDecryptedKey = await crypto2.decrypt.rsa(ownerEncryptedKey, ownerPrivateKey);259 expect(ownerDecryptedKey).to.equal(writerDecryptedKey, "The symmetric keys should be the same after decrypting with the associated private key");260 });261 it("Requires key to add writer", async function() {262 await cli(`keygen tmp/mykeypair`);263 await runCli(`register my-great-repo --private tmp/mykeypair --from ${repoOwner}`);264 expect(await githereumContract.methods.isWriter("my-great-repo", writer).call()).to.not.ok;265 let attemptedAdd = runCli(`add writer my-great-repo ${writer} --from ${repoOwner}`);266 await expect(attemptedAdd).to.be.rejectedWith(/Public and private key is required to add writer to private repo/);267 });268 describe("Reader admin", async function() {269 it("Cannot add readers to a public repo", async function() {270 await runCli(`register my-great-repo --from ${repoOwner}`);271 expect(await githereumContract.methods.isReader("my-great-repo", reader).call()).to.not.ok;272 let attemptedAdd = runCli(`add reader my-great-repo ${reader} --private testkeys/owner --public testkeys/reader --from ${repoOwner}`);273 await expect(attemptedAdd).to.be.rejectedWith(/Repo is not a private repo/);274 expect(await githereumContract.methods.isReader("my-great-repo", reader).call()).to.not.ok;275 });276 it("Repo owners can add readers to a repo", async function() {277 await runCli(`register my-great-repo --private testkeys/owner --from ${repoOwner}`);278 expect(await githereumContract.methods.isPrivate("my-great-repo").call()).to.be.ok;279 expect(await githereumContract.methods.isReader("my-great-repo", reader).call()).to.not.ok;280 await runCli(`add reader my-great-repo ${reader} --private testkeys/owner --public testkeys/reader --from ${repoOwner}`);281 expect(await githereumContract.methods.isReader("my-great-repo", reader).call()).to.be.ok;282 // Can decrypt symmetric key283 let readerPublicKey = fs.readFileSync('testkeys/reader/rsa.pub', 'utf8');284 expect(await githereumContract.methods.publicKey("my-great-repo", reader).call()).to.equal(readerPublicKey);285 let readerPrivateKey = await crypto2.readPrivateKey('testkeys/reader/rsa.pem');286 let ownerPrivateKey = await crypto2.readPrivateKey('testkeys/owner/rsa.pem');287 let ownerEncryptedKey = await githereumContract.methods.encryptedKey("my-great-repo", repoOwner).call();288 let readerEncryptedKey = await githereumContract.methods.encryptedKey("my-great-repo", reader).call();289 let readerDecryptedKey = await crypto2.decrypt.rsa(readerEncryptedKey, readerPrivateKey);290 let ownerDecryptedKey = await crypto2.decrypt.rsa(ownerEncryptedKey, ownerPrivateKey);291 expect(ownerDecryptedKey).to.equal(readerDecryptedKey, "The symmetric keys should be the same after decrypting with the associated private key");292 });293 it("Requires key to add reader", async function() {294 await runCli(`register my-great-repo --private testkeys/owner --from ${repoOwner}`);295 expect(await githereumContract.methods.isReader("my-great-repo", reader).call()).to.not.be.ok;296 let attemptedAdd = runCli(`add reader my-great-repo ${reader} --from ${repoOwner}`);297 await expect(attemptedAdd).to.be.rejectedWith(/Public and private key is required to add reader to private repo/);298 expect(await githereumContract.methods.isReader("my-great-repo", reader).call()).to.not.be.ok;299 });300 it("Repo owners cannot add readers to a repo they do not own", async function() {301 await runCli(`register my-great-repo --private testkeys/owner --from ${repoOwner}`);302 await runCli(`register other-repo --private testkeys/owner --from ${otherOwner}`);303 expect(await githereumContract.methods.isReader("my-great-repo", writer).call()).to.not.ok;304 let attemptedAdd = runCli(`add reader my-great-repo ${reader} --private testkeys/owner --public testkeys/reader --from ${otherOwner}`);305 await expect(attemptedAdd).to.be.rejectedWith(/Only repo owners can add new readers/);306 expect(await githereumContract.methods.isReader("my-great-repo", writer).call()).to.not.ok;307 });308 it("Readers cannot add repo owners to a repo", async function() {309 await runCli(`register my-great-repo --private testkeys/owner --from ${repoOwner}`);310 await runCli(`add reader my-great-repo ${reader} --private testkeys/owner --public testkeys/reader --from ${repoOwner}`);311 let attemptedAdd = runCli(`add owner my-great-repo ${someRandomAddress} --private testkeys/reader --public testkeys/otherowner --from ${reader}`);312 await expect(attemptedAdd).to.be.rejectedWith(/Only repo owners can add new owners/);313 });314 it("Readers cannot add writers to a repo", async function() {315 await runCli(`register my-great-repo --private testkeys/owner --from ${repoOwner}`);316 await runCli(`add reader my-great-repo ${reader} --private testkeys/owner --public testkeys/reader --from ${repoOwner}`);317 let attemptedAdd = runCli(`add writer my-great-repo ${someRandomAddress} --private testkeys/reader --public testkeys/reader --from ${reader}`);318 await expect(attemptedAdd).to.be.rejectedWith(/Only repo owners can add new writers/);319 });320 it("Readers cannot add readers to a repo", async function() {321 await runCli(`register my-great-repo --private testkeys/owner --from ${repoOwner}`);322 await runCli(`add reader my-great-repo ${reader} --private testkeys/owner --public testkeys/reader --from ${repoOwner}`);323 let attemptedAdd = runCli(`add reader my-great-repo ${someRandomAddress} --private testkeys/reader --public testkeys/reader --from ${reader}`);324 await expect(attemptedAdd).to.be.rejectedWith(/Only repo owners can add new readers/);325 });326 it("Readers cannot remove repo owners from a repo", async function() {327 await runCli(`register my-great-repo --private testkeys/owner --from ${repoOwner}`);328 await runCli(`add reader my-great-repo ${reader} --private testkeys/owner --public testkeys/reader --from ${repoOwner}`);329 let attemptedRemove = runCli(`remove owner my-great-repo ${repoOwner} --from ${reader}`);330 await expect(attemptedRemove).to.be.rejectedWith(/Only repo owners can remove owners/);331 });332 it("Readers cannot remove writers from a repo", async function() {333 await runCli(`register my-great-repo --private testkeys/owner --from ${repoOwner}`);334 await runCli(`add writer my-great-repo ${writer} --private testkeys/owner --public testkeys/writer --from ${repoOwner}`);335 await runCli(`add reader my-great-repo ${reader} --private testkeys/owner --public testkeys/reader --from ${repoOwner}`);336 let attemptedRemove = runCli(`remove writer my-great-repo ${writer} --private testkeys/owner --public testkeys/reader --from ${reader}`);337 await expect(attemptedRemove).to.be.rejectedWith(/Only repo owners can remove writers/);338 });339 it("Readers cannot remove readers from a repo", async function() {340 await runCli(`register my-great-repo --private testkeys/owner --from ${repoOwner}`);341 await runCli(`add reader my-great-repo ${reader} --private testkeys/owner --public testkeys/reader --from ${repoOwner}`);342 await runCli(`add reader my-great-repo ${otherReader} --private testkeys/owner --public testkeys/reader --from ${repoOwner}`);343 let attemptedRemove = runCli(`remove reader my-great-repo ${otherReader} --from ${reader}`);344 await expect(attemptedRemove).to.be.rejectedWith(/Only repo owners can remove reader/);345 });346 it("Writers cannot add readers to a repo", async function() {347 await runCli(`register my-great-repo --private testkeys/owner --from ${repoOwner}`);348 await runCli(`add writer my-great-repo ${writer} --private testkeys/owner --public testkeys/writer --from ${repoOwner}`);349 let attemptedAdd = runCli(`add reader my-great-repo ${someRandomAddress} --private testkeys/writer --public testkeys/reader --from ${writer}`);350 await expect(attemptedAdd).to.be.rejectedWith(/Only repo owners can add new readers/);351 });352 it("Writers cannot remove readers from a repo", async function() {353 await runCli(`register my-great-repo --private testkeys/owner --from ${repoOwner}`);354 await runCli(`add writer my-great-repo ${writer} --private testkeys/owner --public testkeys/writer --from ${repoOwner}`);355 await runCli(`add reader my-great-repo ${reader} --private testkeys/owner --public testkeys/reader --from ${repoOwner}`);356 let attemptedRemove = runCli(`remove reader my-great-repo ${reader} --private testkeys/writer --public testkeys/reader --from ${writer}`);357 await expect(attemptedRemove).to.be.rejectedWith(/Only repo owners can remove readers/);358 });359 });360 it("pushes a simple repo to the blockchain and restores it again using a private repo", async() => {361 await setupFixtureRepo('dummygit');362 await runCli(`register my-repo --private testkeys/owner --from ${repoOwner}`);363 await runCli(`push tmp/dummygit my-repo:my-tag --private testkeys/owner --from ${repoOwner}`);364 // the objects should be stored in the object store365 let blobs = await glob('tmp/blobs/*');366 expect(blobs.length).to.equal(1);367 await runCli(`clone my-repo:my-tag tmp/cloned --private testkeys/owner --from ${repoOwner}`);368 let fullRef = await Git.resolveRef({ dir: 'tmp/cloned', ref: 'master' });369 expect(fullRef).to.equal('a47c8dc067a1648896f7de6759d25411f8f665a0');370 let commits = await Git.log({ dir: 'tmp/cloned' });371 expect(commits.length).to.equal(4);372 expect(commits.map(c => c.oid)).to.deep.equal(["a47c8dc067a1648896f7de6759d25411f8f665a0", "247e877ae8a62139e3561fd95ac3cfa48cbfab97", "23e65d5097a41c4f6f9b2937f807c78296ea3298", "b5d928ed34f07b13cb2c664903b771b12ad2ca29"]);373 expect(fs.readFileSync('tmp/cloned/README', 'utf8')).to.equal("Hello World\n");374 });375 });376 describe("Repo operations", async function() {377 this.slow(2000);378 it("pushes a simple repo to the blockchain and restores it again", async() => {379 await setupFixtureRepo('dummygit');380 await runCli(`register my-repo --from ${repoOwner}`);381 await runCli(`push tmp/dummygit my-repo:my-tag --from ${repoOwner}`);382 // the objects should be stored in the object store383 let blobs = await glob('tmp/blobs/*');384 expect(blobs.length).to.equal(1);385 await runCli(`clone my-repo:my-tag tmp/cloned`);386 let fullRef = await Git.resolveRef({ dir: 'tmp/cloned', ref: 'master' });387 expect(fullRef).to.equal('a47c8dc067a1648896f7de6759d25411f8f665a0');388 let commits = await Git.log({ dir: 'tmp/cloned' });389 expect(commits.length).to.equal(4);390 expect(commits.map(c => c.oid)).to.deep.equal(["a47c8dc067a1648896f7de6759d25411f8f665a0", "247e877ae8a62139e3561fd95ac3cfa48cbfab97", "23e65d5097a41c4f6f9b2937f807c78296ea3298", "b5d928ed34f07b13cb2c664903b771b12ad2ca29"]);391 expect(fs.readFileSync('tmp/cloned/README', 'utf8')).to.equal("Hello World\n");392 });393 it("pushes a repo to the blockchain and restores it again when the repo uses packfiles", async() => {394 await setupFixtureRepo('dummygit-packed');395 await runCli(`register my-repo --from ${repoOwner}`);396 await runCli(`push tmp/dummygit-packed my-repo:packed-tag --from ${repoOwner}`);397 // the objects should be stored in the object store398 let blobs = await glob('tmp/blobs/*');399 expect(blobs.length).to.equal(1);400 await runCli(`clone my-repo:packed-tag tmp/cloned`);401 let fullRef = await Git.resolveRef({ dir: 'tmp/cloned', ref: 'master' });402 expect(fullRef).to.equal('a47c8dc067a1648896f7de6759d25411f8f665a0');403 let commits = await Git.log({ dir: 'tmp/cloned' });404 expect(commits.length).to.equal(4);405 expect(commits.map(c => c.oid)).to.deep.equal(["a47c8dc067a1648896f7de6759d25411f8f665a0", "247e877ae8a62139e3561fd95ac3cfa48cbfab97", "23e65d5097a41c4f6f9b2937f807c78296ea3298", "b5d928ed34f07b13cb2c664903b771b12ad2ca29"]);406 expect(fs.readFileSync('tmp/cloned/README', 'utf8')).to.equal("Hello World\n");407 });408 it("pushes a repo to the blockchain and restores it again when the repo has commits with multiple parents", async() => {409 await setupFixtureRepo('repo-with-merge');410 await runCli(`register merge --from ${repoOwner}`);411 await runCli(`push tmp/repo-with-merge merge:merged-tag --from ${repoOwner}`);412 // the objects should be stored in the object store413 let blobs = await glob('tmp/blobs/*');414 expect(blobs.length).to.equal(1);415 await runCli(`clone merge:merged-tag tmp/cloned`);416 let fullRef = await Git.resolveRef({ dir: 'tmp/cloned', ref: 'master' });417 expect(fullRef).to.equal('93ae4072e3660b23b30b80cfc98620dfbe20ca85');418 let commits = await Git.log({ dir: 'tmp/cloned' });419 expect(commits.length).to.equal(7);420 expect(commits.map(c => c.oid)).to.deep.equal(["93ae4072e3660b23b30b80cfc98620dfbe20ca85", "54663b63174fc953678bea90602f1cf44d86dc15", "ce28caec25546c289f53ee749851848104e5e47f", "a47c8dc067a1648896f7de6759d25411f8f665a0", "247e877ae8a62139e3561fd95ac3cfa48cbfab97", "23e65d5097a41c4f6f9b2937f807c78296ea3298", "b5d928ed34f07b13cb2c664903b771b12ad2ca29"]);421 expect(fs.readFileSync('tmp/cloned/README', 'utf8')).to.equal("Hello World - version C\n");422 });423 it("works with bare repos", async() => {424 await setupBareFixtureRepo('dummygit');425 await runCli(`register bare --from ${repoOwner}`);426 await runCli(`push tmp/dummygit bare:bare-tag --from ${repoOwner}`);427 // the objects should be stored in the object store428 let blobs = await glob('tmp/blobs/*');429 expect(blobs.length).to.equal(1);430 await runCli(`clone bare:bare-tag tmp/cloned`);431 let fullRef = await Git.resolveRef({ dir: 'tmp/cloned', ref: 'master' });432 expect(fullRef).to.equal('a47c8dc067a1648896f7de6759d25411f8f665a0');433 let commits = await Git.log({ dir: 'tmp/cloned' });434 expect(commits.length).to.equal(4);435 expect(commits.map(c => c.oid)).to.deep.equal(["a47c8dc067a1648896f7de6759d25411f8f665a0", "247e877ae8a62139e3561fd95ac3cfa48cbfab97", "23e65d5097a41c4f6f9b2937f807c78296ea3298", "b5d928ed34f07b13cb2c664903b771b12ad2ca29"]);436 expect(fs.readFileSync('tmp/cloned/README', 'utf8')).to.equal("Hello World\n");437 });438 it("pushes an update to a tag to the blockchain", async() => {439 await shellCommand("mkdir tmp/dummy-repo");440 await runCli(`register update --from ${repoOwner}`);441 await Git.init({ dir: 'tmp/dummy-repo' });442 let shas = [];443 async function writeDummyCommit(content) {444 fs.writeFileSync("tmp/dummy-repo/content.txt", content);445 await Git.add({ dir: 'tmp/dummy-repo', filepath: 'content.txt' });446 return await Git.commit({447 dir: 'tmp/dummy-repo',448 author: {449 name: 'Mr. Test',450 email: 'mrtest@example.com'451 },452 message: `Commit ${content}`453 });454 }455 for (let content of ["a", "b"]) {456 let sha = await writeDummyCommit(content);457 shas.push(sha);458 }459 await runCli(`push tmp/dummy-repo update:incremental-tag --from ${repoOwner}`);460 // the objects should be stored in the object store461 let blobs = await glob('tmp/blobs/*');462 expect(blobs.length).to.equal(1);463 let headSha = await githereumContract.methods.head('update', 'incremental-tag').call();464 let firstPushSha = shas[shas.length - 1];465 expect(headSha).to.equal(firstPushSha);466 let previousPushHeadSha = await githereumContract.methods.previousPushHeadSha('update', headSha).call();467 expect(previousPushHeadSha).to.not.be.ok;468 expect(previousPushHeadSha.length).to.not.be.ok;469 let packSha = await githereumContract.methods.pack('update', firstPushSha).call();470 expect(packSha).to.be.ok;471 expect(packSha.length).to.be.ok;472 let firstPackSha = packSha;473 expect(await getHead('update:incremental-tag')).to.equal(firstPushSha);474 for (let content of ["c", "d"]) {475 let sha = await writeDummyCommit(content);476 shas.push(sha);477 }478 await runCli(`push tmp/dummy-repo update:incremental-tag --from ${repoOwner}`);479 headSha = await githereumContract.methods.head('update', 'incremental-tag').call();480 expect(headSha).to.equal(shas[shas.length - 1]);481 previousPushHeadSha = await githereumContract.methods.previousPushHeadSha('update', headSha).call();482 expect(previousPushHeadSha).to.equal(firstPushSha);483 packSha = await githereumContract.methods.pack('update', shas[shas.length - 1]).call();484 expect(packSha).not.to.equal(firstPackSha);485 expect(await getHead('update:incremental-tag')).to.equal(shas[shas.length - 1]);486 });487 it("Pulls an updated tag from the blockchain", async() => {488 await shellCommand("mkdir tmp/dummy-repo");489 await runCli(`register update --from ${repoOwner}`);490 await Git.init({ dir: 'tmp/dummy-repo' });491 let shas = [];492 async function writeDummyCommit(content) {493 fs.writeFileSync("tmp/dummy-repo/content.txt", content);494 await Git.add({ dir: 'tmp/dummy-repo', filepath: 'content.txt' });495 return await Git.commit({496 dir: 'tmp/dummy-repo',497 author: {498 name: 'Mr. Test',499 email: 'mrtest@example.com'500 },501 message: `Commit ${content}`502 });503 }504 for (let content of ["a", "b"]) {505 let sha = await writeDummyCommit(content);506 shas.push(sha);507 }508 await runCli(`push tmp/dummy-repo update:pull-tag --from ${repoOwner}`);509 let head = await getHead('update:pull-tag');510 expect(head).to.equal(shas[shas.length - 1]);511 await runCli(`clone update:pull-tag tmp/cloned`);512 let fullRef = await Git.resolveRef({ dir: 'tmp/cloned', ref: 'master' });513 expect(fullRef).to.equal(head);514 let commits = await Git.log({ dir: 'tmp/cloned' });515 expect(commits.length).to.equal(2);516 expect(commits.map(c => c.oid)).to.deep.equal(shas.slice().reverse());517 expect(fs.readFileSync('tmp/cloned/content.txt', 'utf8')).to.equal("b");518 for (let content of ["c", "d"]) {519 let sha = await writeDummyCommit(content);520 shas.push(sha);521 }522 await runCli(`push tmp/dummy-repo update:pull-tag --from ${repoOwner}`);523 head = await getHead('update:pull-tag');524 expect(head).to.equal(shas[shas.length - 1]);525 await runCli(`pull update:pull-tag tmp/cloned`);526 fullRef = await Git.resolveRef({ dir: 'tmp/cloned', ref: 'master' });527 expect(fullRef).to.equal(head);528 commits = await Git.log({ dir: 'tmp/cloned' });529 expect(commits.length).to.equal(4);530 expect(commits.map(c => c.oid)).to.deep.equal(shas.slice().reverse());531 expect(fs.readFileSync('tmp/cloned/content.txt', 'utf8')).to.equal("d");532 });533 });...
cli.test.js
Source:cli.test.js
1// Test the CLI directly2const fs = require('fs')3const path = require('path')4const test = require('ava')5const {spawn} = require('cross-spawn')6const run = require('inquirer-test')7const {ENTER} = require('inquirer-test')8const {version} = require('../package.json')9const runcli = (...args) => {10 return new Promise((resolve, reject) => {11 const command = path.resolve(__dirname, '../bin/data.js')12 args.push('--test')13 const data = spawn(command, args)14 let stdout = ''15 data.stdout.on('data', data => {16 stdout += data17 })18 data.on('error', err => {19 reject(err)20 })21 data.on('close', code => {22 resolve({23 code,24 stdout25 })26 })27 })28}29// ==========30// The basics31test.after.always('cleanup', t => {32 let deleteFolderRecursive = (path) => {33 if (fs.existsSync(path)) {34 fs.readdirSync(path).forEach((file, index) => {35 let curPath = path + "/" + file;36 if (fs.lstatSync(curPath).isDirectory()) { // recurse37 deleteFolderRecursive(curPath);38 } else { // delete file39 fs.unlinkSync(curPath);40 }41 })42 fs.rmdirSync(path);43 }44 }45 deleteFolderRecursive('finance-vix')46 deleteFolderRecursive('test/small-dataset-100kb')47 deleteFolderRecursive('test/medium-dataset-1mb')48 deleteFolderRecursive('test/big-dataset-10mb')49 deleteFolderRecursive('test/private-cli-test')50 try {51 fs.unlinkSync('test/fixtures/test-data/files/geo/datapackage.json')52 fs.unlinkSync('sample.csv')53 fs.unlinkSync('sample-1-sheet.xls')54 fs.unlinkSync('0.csv')55 } catch (err) {56 console.log('Finished cleanup without deleting some files.')57 }58})59test('"data -v --version" prints version', async t => {60 let result = await runcli('-v')61 t.is(result.code, 0)62 let stdout = result.stdout.split('\n')63 t.true(stdout.length > 1)64 t.true(stdout[0].includes(`${version}`))65 result = await runcli('--version')66 t.is(result.code, 0)67 stdout = result.stdout.split('\n')68 t.true(stdout.length > 1)69 t.true(stdout[0].includes(`${version}`))70})71test('"data help" prints help message', async t => {72 const result = await runcli('help')73 t.is(result.code, 0)74 const stdout = result.stdout.split('\n')75 t.true(stdout.length > 1)76 const hasExpectedMsg = stdout.find(item => item.includes('â data [options] <command> <args>'))77 t.truthy(hasExpectedMsg)78})79// =======================================80// DATA-CLI GET81test('get command with local dataset', async t => {82 const identifier = 'test/fixtures/finance-vix'83 const result = await runcli('get', identifier)84 const stdout = result.stdout.split('\n')85 const hasTimeElapsedMsg = stdout.find(item => item.includes('Time elapsed:'))86 const hasSuccessMsg = stdout.find(item => item.includes('Dataset/file is saved in "finance-vix"'))87 t.truthy(hasTimeElapsedMsg)88 t.truthy(hasSuccessMsg)89})90test('get command with local file', async t => {91 const identifier = 'test/fixtures/sample.csv'92 const result = await runcli('get', identifier)93 const stdout = result.stdout.split('\n')94 const hasTimeElapsedMsg = stdout.find(item => item.includes('Time elapsed:'))95 const hasSuccessMsg = stdout.find(item => item.includes('Dataset/file is saved in "sample.csv"'))96 t.truthy(hasTimeElapsedMsg)97 t.truthy(hasSuccessMsg)98})99// QA tests [Get: r links from DataHub]100test('get command with r links from DataHub', async t => {101 const identifier = 'https://datahub.io/test/small-dataset-100kb/r/0.csv'102 const result = await runcli('get', identifier)103 const stdout = result.stdout.split('\n')104 const hasTimeElapsedMsg = stdout.find(item => item.includes('Time elapsed:'))105 const hasSuccessMsg = stdout.find(item => item.includes('Dataset/file is saved in "0.csv"'))106 t.truthy(hasTimeElapsedMsg)107 t.truthy(hasSuccessMsg)108})109// end of [Get: r links from DataHub]110// QA tests [Get: Small dataset from DataHub]111test('get command with small dataset from DataHub', async t => {112 const identifier = 'https://datahub.io/test/small-dataset-100kb/'113 const result = await runcli('get', identifier)114 const stdout = result.stdout.split('\n')115 const hasTimeElapsedMsg = stdout.find(item => item.includes('Time elapsed:'))116 const hasSuccessMsg = stdout.find(item => item.includes('Dataset/file is saved in "test/small-dataset-100kb"'))117 t.truthy(hasTimeElapsedMsg)118 t.truthy(hasSuccessMsg)119})120// end of [Get: Small dataset from DataHub]121// QA tests [Get: Medium dataset from DataHub]122test('get command with medium dataset from DataHub', async t => {123 const identifier = 'https://datahub.io/test/medium-dataset-1mb'124 const result = await runcli('get', identifier)125 const stdout = result.stdout.split('\n')126 const hasTimeElapsedMsg = stdout.find(item => item.includes('Time elapsed:'))127 const hasSuccessMsg = stdout.find(item => item.includes('Dataset/file is saved in "test/medium-dataset-1mb"'))128 t.truthy(hasTimeElapsedMsg)129 t.truthy(hasSuccessMsg)130})131// end of [Get: Meduim dataset from DataHub]132// QA tests [Get: Big dataset from DataHub]133test('get command with big dataset from DataHub', async t => {134 const identifier = 'https://datahub.io/test/big-dataset-10mb'135 const result = await runcli('get', identifier)136 const stdout = result.stdout.split('\n')137 const hasTimeElapsedMsg = stdout.find(item => item.includes('Time elapsed:'))138 const hasSuccessMsg = stdout.find(item => item.includes('Dataset/file is saved in "test/big-dataset-10mb"'))139 t.truthy(hasTimeElapsedMsg)140 t.truthy(hasSuccessMsg)141})142// end of [Get: Big dataset from DataHub]143// QA tests [Get: get excel file]144test('get command with excel file', async t => {145 const identifier = 'https://github.com/frictionlessdata/test-data/blob/master/files/excel/sample-1-sheet.xls'146 const result = await runcli('get', identifier)147 const stdout = result.stdout.split('\n')148 const hasTimeElapsedMsg = stdout.find(item => item.includes('Time elapsed:'))149 const hasSuccessMsg = stdout.find(item => item.includes('Dataset/file is saved in "sample-1-sheet.xls"'))150 t.truthy(hasTimeElapsedMsg)151 t.truthy(hasSuccessMsg)152})153// end of [Get: get excel file]154// QA tests [Get: get private dataset]155test('get command with private dataset', async t => {156 const identifier = 'https://datahub.io/test/private-cli-test'157 // Note that token for test user is set in env var. First we pass wrong token158 // as an argument and expect 404 or 403:159 const token = 'non-owner-token'160 let result = await runcli('get', identifier, `--token=${token}`)161 let stdout = result.stdout.split('\n')162 const hasErrorMsg = stdout.find(item => item.includes('> Error! 404: Not Found. Requested URL'))163 t.truthy(hasErrorMsg)164 // Now use correct token from env var:165 result = await runcli('get', identifier)166 stdout = result.stdout.split('\n')167 const hasTimeElapsedMsg = stdout.find(item => item.includes('Time elapsed:'))168 t.truthy(hasTimeElapsedMsg)169 t.true(fs.existsSync('test/private-cli-test/datapackage.json'))170})171// end of QA tests [Get: get private dataset]172// =======================================173// CLI commands: validate, cat, info, init174test('Init command in non-interactive mode', async t => {175 const result = await runcli('init', 'test/fixtures/test-data/files/geo/')176 t.true(result.stdout.includes('This process initializes a new datapackage.json file'))177 t.true(result.stdout.includes('Descriptor is saved in'))178})179// QA tests [Info: basic dataset]180test('Info: basic dataset', async t => {181 let identifier = 'test/fixtures/test-data/packages/basic-csv'182 let result = await runcli('info', identifier)183 let stdout = result.stdout.split('\n')184 let hasMsg = stdout.find(item => item.includes('# basic-csv'))185 t.truthy(hasMsg)186 hasMsg = stdout.find(item => item.includes('comma-separated'))187 t.truthy(hasMsg)188 identifier = 'https://github.com/frictionlessdata/test-data/tree/master/packages/basic-csv'189 result = await runcli('info', identifier)190 stdout = result.stdout.split('\n')191 hasMsg = stdout.find(item => item.includes('# basic-csv'))192 t.truthy(hasMsg)193 hasMsg = stdout.find(item => item.includes('comma-separated'))194 t.truthy(hasMsg)195})196// end of [Info: basic dataset]197// QA tests [Info: dataset with multiple resources]198test('Info: dataset with multiple resources', async t => {199 let identifier = 'test/fixtures/test-data/packages/different-separators'200 let result = await runcli('info', identifier)201 let stdout = result.stdout.split('\n')202 let hasCaretsResource = stdout.find(item => item.includes('carets'))203 let hasCommaResource = stdout.find(item => item.includes('comma'))204 t.truthy(hasCaretsResource)205 t.truthy(hasCommaResource)206 identifier = 'https://github.com/frictionlessdata/test-data/tree/master/packages/different-separators'207 result = await runcli('info', identifier)208 stdout = result.stdout.split('\n')209 hasCaretsResource = stdout.find(item => item.includes('carets'))210 hasCommaResource = stdout.find(item => item.includes('comma'))211 t.truthy(hasCaretsResource)212 t.truthy(hasCommaResource)213})214// end if [Info: dataset with multiple resources]215// QA tests [Info: basic CSV]216test('Info: basic CSV', async t => {217 let identifier = 'test/fixtures/test-data/files/csv/100kb.csv'218 let result = await runcli('info', identifier)219 let stdout = result.stdout.split('\n')220 let hasDialect = stdout.find(item => item.includes('dialect'))221 let hasSchema = stdout.find(item => item.includes('schema'))222 let hasEncodings = stdout.find(item => item.includes('encoding'))223 let hasCreatedDate = stdout.find(item => item.includes('created'))224 let hasValueInTheTenthRow = stdout.find(item => item.includes('Sharlene'))225 let hasValueInTheEleventhRow = stdout.find(item => item.includes('Misti'))226 t.truthy(hasDialect)227 t.truthy(hasSchema)228 t.truthy(hasEncodings)229 t.falsy(hasCreatedDate)230 t.truthy(hasValueInTheTenthRow)231 t.falsy(hasValueInTheEleventhRow)232})233// end of [Info: basic CSV]234// QA tests [Info: non-tabular file]235test('Info: non-tabular file', async t => {236 let identifier = 'test/fixtures/test-data/files/other/sample.pdf'237 let result = await runcli('info', identifier)238 let stdout = result.stdout.split('\n')239 let hasName = stdout.find(item => item.includes('name'))240 let hasFormat = stdout.find(item => item.includes('format'))241 let hasPath = stdout.find(item => item.includes('path'))242 let hasDialect = stdout.find(item => item.includes('dialect'))243 t.truthy(hasName)244 t.truthy(hasFormat)245 t.truthy(hasPath)246 t.falsy(hasDialect)247 identifier = 'https://github.com/frictionlessdata/test-data/raw/master/files/other/sample.pdf'248 result = await runcli('info', identifier)249 stdout = result.stdout.split('\n')250 hasName = stdout.find(item => item.includes('name'))251 hasFormat = stdout.find(item => item.includes('format'))252 hasPath = stdout.find(item => item.includes('path'))253 hasDialect = stdout.find(item => item.includes('dialect'))254 t.truthy(hasName)255 t.truthy(hasFormat)256 t.truthy(hasPath)257 t.falsy(hasDialect)258})259// QA tests [Info: from datahub and github]260test('info command with a dataset from GitHub', async t => {261 const identifier = 'https://github.com/datasets/finance-vix'262 const result = await runcli('info', identifier)263 const stdout = result.stdout.split('\n')264 const hasReadme = stdout.find(item => item.includes('CBOE Volatility Index (VIX) time-series dataset including'))265 const hasResource = stdout.find(item => item.includes('vix-daily'))266 t.truthy(hasReadme)267 t.truthy(hasResource)268})269test('info command with a dataset from DataHub', async t => {270 const identifier = 'https://datahub.io/core/finance-vix'271 const result = await runcli('info', identifier)272 const stdout = result.stdout.split('\n')273 const hasReadme = stdout.find(item => item.includes('CBOE Volatility Index (VIX) time-series dataset including'))274 const hasResource = stdout.find(item => item.includes('vix-daily'))275 t.truthy(hasReadme)276 t.truthy(hasResource)277})278// end of [Info: from datahub and github]279// QA tests [Proper error messages]280test('info command - no dataset or descriptor at URL', async t => {281 const url_ = 'https://datahub.io'282 const result = await runcli('info', url_)283 const stdout = result.stdout.split('\n')284 const hasErrorMsg = stdout.find(item => item.includes('Expected URL to a dataset or descriptor.'))285 t.truthy(hasErrorMsg)286})287test('get command - no dataset or descriptor at URL', async t => {288 const url_ = 'https://datahub.io'289 const result = await runcli('get', url_)290 const stdout = result.stdout.split('\n')291 const hasErrorMsg = stdout.find(item => item.includes('Expected URL to a dataset or descriptor.'))292 t.truthy(hasErrorMsg)293})294// end of [Proper error messages]295// QA tests [Validate: basic csv resource]296test('validate command - basic dataset', async t => {297 const path_ = 'test/fixtures/test-data/packages/basic-csv'298 const result = await runcli('validate', path_)299 const stdout = result.stdout.split('\n')300 const hasValidMessage = stdout.find(item => item.includes('Your Data Package is valid!'))301 t.truthy(hasValidMessage)302})303test.serial('validate command - remote basic dataset', async t => {304 const url_ = 'https://github.com/frictionlessdata/test-data/tree/master/packages/basic-csv'305 const result = await runcli('validate', url_)306 const stdout = result.stdout.split('\n')307 const hasValidMessage = stdout.find(item => item.includes('Your Data Package is valid!'))308 t.truthy(hasValidMessage)309})310// end of [Validate: basic csv resource]311// QA tests [Validate: non-tabular resource LOCALLY]312test('validate command - non-tabular resource', async t => {313 const path_ = 'test/fixtures/test-data/packages/non-tabular-resource'314 const result = await runcli('validate', path_)315 const stdout = result.stdout.split('\n')316 const hasValidMessage = stdout.find(item => item.includes('Your Data Package is valid!'))317 t.truthy(hasValidMessage)318})319test.serial('validate command - remote dataset with non-tabular resource', async t => {320 const url_ = 'https://github.com/frictionlessdata/test-data/tree/master/packages/non-tabular-resource'321 const result = await runcli('validate', url_)322 const stdout = result.stdout.split('\n')323 const hasValidMessage = stdout.find(item => item.includes('Your Data Package is valid!'))324 t.truthy(hasValidMessage)325})326// end of [Validate: non-tabular resource LOCALLY]327// QA tests [Validate: remote resource]328test('validate command - remote resource', async t => {329 const path_ = 'test/fixtures/test-data/packages/remote-csv'330 const result = await runcli('validate', path_)331 const stdout = result.stdout.split('\n')332 const hasValidMessage = stdout.find(item => item.includes('Your Data Package is valid!'))333 t.truthy(hasValidMessage)334})335test.serial('validate command - remote dataset with remote resource', async t => {336 const url_ = 'https://github.com/frictionlessdata/test-data/tree/master/packages/remote-csv'337 const result = await runcli('validate', url_)338 const stdout = result.stdout.split('\n')339 const hasValidMessage = stdout.find(item => item.includes('Your Data Package is valid!'))340 t.truthy(hasValidMessage)341})342// end of [Validate: remote resource]343// QA tests [Validate: csv with different separators]344test('validate command - csv with different separators', async t => {345 const path_ = 'test/fixtures/test-data/packages/different-separators'346 const result = await runcli('validate', path_)347 const stdout = result.stdout.split('\n')348 const hasValidMessage = stdout.find(item => item.includes('Your Data Package is valid!'))349 t.truthy(hasValidMessage)350})351test.serial('validate command - remote dataset with csv with different separators', async t => {352 const url_ = 'https://github.com/frictionlessdata/test-data/tree/master/packages/different-separators'353 const result = await runcli('validate', url_)354 const stdout = result.stdout.split('\n')355 const hasValidMessage = stdout.find(item => item.includes('Your Data Package is valid!'))356 t.truthy(hasValidMessage)357})358// end of [Validate: csv with different separators]359// QA tests [Validate: invalid path to resource]360test('validate command - invalid local path', async t => {361 const path_ = 'test/fixtures/test-data/packages/invalid-local-path'362 const result = await runcli('validate', path_)363 const stdout = result.stdout.split('\n')364 const hasErrorMsg = stdout.find(item => item.includes('> Error! ENOENT: no such file or directory'))365 t.truthy(hasErrorMsg)366})367// end of [Validate: invalid path to resource]368// QA tests [Validate: invalid remote path to resource]369test.serial('validate command - invalid remote path for resource', async t => {370 const path_ = 'test/fixtures/test-data/packages/invalid-remote-path'371 const result = await runcli('validate', path_)372 const stdout = result.stdout.split('\n')373 const hasErrorMsg = stdout.find(item => item.includes('> Error! Request failed with status code 404'))374 const hasResourceName = stdout.find(item => item.includes('> Error! Resource: invalid-remote-path'))375 const hasResourcePath = stdout.find(item => item.includes('> Error! Path: https://raw.githubusercontent.com/frictionlessdata/there/is/no/such/file.csv'))376 t.truthy(hasErrorMsg)377 t.truthy(hasResourceName)378 t.truthy(hasResourcePath)379})380test.serial('validate command - remote dataset with invalid remote path for resource', async t => {381 const url_ = 'https://github.com/frictionlessdata/test-data/tree/master/packages/invalid-remote-path'382 const result = await runcli('validate', url_)383 const stdout = result.stdout.split('\n')384 const hasErrorMsg = stdout.find(item => item.includes('> Error! Request failed with status code 404'))385 const hasResourceName = stdout.find(item => item.includes('> Error! Resource: invalid-remote-path'))386 const hasResourcePath = stdout.find(item => item.includes('> Error! Path: https://raw.githubusercontent.com/frictionlessdata/there/is/no/such/file.csv'))387 t.truthy(hasErrorMsg)388 t.truthy(hasResourceName)389 t.truthy(hasResourcePath)390})391// end of [Validate: invalid remote path to resource]392// QA tests [Validate: csv with different field types, formats and constraints]393test.serial('validate command - wrong constraints', async t => {394 const path_ = 'test/fixtures/test-data/packages/types-formats-and-constraints/constraints'395 let result = await runcli('validate', path_)396 let stdout = result.stdout.split('\n')397 let hasErrorMsg = stdout.find(item => item.includes('> Error! There are 7 type and format mismatch errors on line 3'))398 t.truthy(hasErrorMsg)399 const url_ = 'https://github.com/frictionlessdata/test-data/tree/master/packages/types-formats-and-constraints/constraints'400 result = await runcli('validate', url_)401 stdout = result.stdout.split('\n')402 hasErrorMsg = stdout.find(item => item.includes('> Error! There are 7 type and format mismatch errors on line 3'))403 t.truthy(hasErrorMsg)404})405test.serial('validate command - wrong "date" type/format', async t => {406 const path_ = 'test/fixtures/test-data/packages/types-formats-and-constraints/date'407 let result = await runcli('validate', path_)408 let stdout = result.stdout.split('\n')409 let hasErrorMsg = stdout.find(item => item.includes('> Error! There are 2 type and format mismatch errors on line 3'))410 t.truthy(hasErrorMsg)411 const url_ = 'https://github.com/frictionlessdata/test-data/tree/master/packages/types-formats-and-constraints/date'412 result = await runcli('validate', url_)413 stdout = result.stdout.split('\n')414 hasErrorMsg = stdout.find(item => item.includes('> Error! There are 2 type and format mismatch errors on line 3'))415 t.truthy(hasErrorMsg)416})417test.serial('validate command - wrong "datetime" type/format', async t => {418 const path_ = 'test/fixtures/test-data/packages/types-formats-and-constraints/datetime'419 let result = await runcli('validate', path_)420 let stdout = result.stdout.split('\n')421 let hasErrorMsg = stdout.find(item => item.includes('> Error! There are 3 type and format mismatch errors on line 3'))422 t.truthy(hasErrorMsg)423 const url_ = 'https://github.com/frictionlessdata/test-data/tree/master/packages/types-formats-and-constraints/datetime'424 result = await runcli('validate', url_)425 stdout = result.stdout.split('\n')426 hasErrorMsg = stdout.find(item => item.includes('> Error! There are 3 type and format mismatch errors on line 3'))427 t.truthy(hasErrorMsg)428})429test.serial('validate command - wrong "string" type/format', async t => {430 const path_ = 'test/fixtures/test-data/packages/types-formats-and-constraints/string'431 let result = await runcli('validate', path_)432 let stdout = result.stdout.split('\n')433 let hasErrorMsg = stdout.find(item => item.includes('> Error! There are 3 type and format mismatch errors on line 3'))434 t.truthy(hasErrorMsg)435 const url_ = 'https://github.com/frictionlessdata/test-data/tree/master/packages/types-formats-and-constraints/string'436 result = await runcli('validate', url_)437 stdout = result.stdout.split('\n')438 hasErrorMsg = stdout.find(item => item.includes('> Error! There are 3 type and format mismatch errors on line 3'))439 t.truthy(hasErrorMsg)440})441test.serial('validate command - wrong "time" type/format', async t => {442 const path_ = 'test/fixtures/test-data/packages/types-formats-and-constraints/time'443 let result = await runcli('validate', path_)444 let stdout = result.stdout.split('\n')445 let hasErrorMsg = stdout.find(item => item.includes('> Error! There are 3 type and format mismatch errors on line 3'))446 t.truthy(hasErrorMsg)447 const url_ = 'https://github.com/frictionlessdata/test-data/tree/master/packages/types-formats-and-constraints/time'448 result = await runcli('validate', url_)449 stdout = result.stdout.split('\n')450 hasErrorMsg = stdout.find(item => item.includes('> Error! There are 3 type and format mismatch errors on line 3'))451 t.truthy(hasErrorMsg)452})453test.serial('validate command - wrong "year" type/format', async t => {454 const path_ = 'test/fixtures/test-data/packages/types-formats-and-constraints/year'455 let result = await runcli('validate', path_)456 let stdout = result.stdout.split('\n')457 let hasErrorMsg = stdout.find(item => item.includes('> Error! There are 1 type and format mismatch errors on line 2'))458 t.truthy(hasErrorMsg)459 const url_ = 'https://github.com/frictionlessdata/test-data/tree/master/packages/types-formats-and-constraints/year'460 result = await runcli('validate', url_)461 stdout = result.stdout.split('\n')462 hasErrorMsg = stdout.find(item => item.includes('> Error! There are 1 type and format mismatch errors on line 2'))463 t.truthy(hasErrorMsg)464})465test.serial('validate command - wrong "yearmonth" type/format', async t => {466 const path_ = 'test/fixtures/test-data/packages/types-formats-and-constraints/yearmonth'467 let result = await runcli('validate', path_)468 let stdout = result.stdout.split('\n')469 let hasErrorMsg = stdout.find(item => item.includes('> Error! There are 1 type and format mismatch errors on line 2'))470 t.truthy(hasErrorMsg)471 const url_ = 'https://github.com/frictionlessdata/test-data/tree/master/packages/types-formats-and-constraints/yearmonth'472 result = await runcli('validate', url_)473 stdout = result.stdout.split('\n')474 hasErrorMsg = stdout.find(item => item.includes('> Error! There are 1 type and format mismatch errors on line 2'))475 t.truthy(hasErrorMsg)476})477// end of [Validate: csv with different field types, formats and constraints]478// QA tests [Cat: basic csv]479test('cat command - basic behaviour', async t => {480 const path_ = 'test/fixtures/test-data/files/csv/all-schema-types.csv'481 const results = await runcli('cat', path_)482 const stdout = results.stdout.split('\n')483 const hasMsg = stdout.find(item => item.includes('â 1.0 â'))484 t.truthy(hasMsg)485})486test('cat command - remote csv file', async t => {487 const url_ = 'https://raw.githubusercontent.com/frictionlessdata/test-data/master/files/csv/all-schema-types.csv'488 const results = await runcli('cat', url_)489 const stdout = results.stdout.split('\n')490 const hasMsg = stdout.find(item => item.includes('â 1.0 â'))491 t.truthy(hasMsg)492})493test('cat command - remote non tabular file', async t => {494 const url_ = 'https://raw.githubusercontent.com/frictionlessdata/test-data/master/files/other/sample.txt'495 const results = await runcli('cat', url_)496 const stdout = results.stdout.split('\n')497 const hasErrorMsg = stdout.find(item => item.includes('> Error! We do not have a parser for that format: txt'))498 t.truthy(hasErrorMsg)499})500test('cat command - non-existing path', async t => {501 const path_ = 'non/existing/path'502 const results = await runcli('cat', path_)503 const stdout = results.stdout.split('\n')504 const hasErrorMsg = stdout.find(item => item.includes('> Error! ENOENT: no such file or directory'))505 t.truthy(hasErrorMsg)506})507test('cat command - URL that returns 404', async t => {508 const url_ = 'https://raw.githubusercontent.com/frictionlessdata/test-data/master/files/other/sampl.csv'509 const results = await runcli('cat', url_)510 const stdout = results.stdout.split('\n')511 let hasErrorMsg = stdout.find(item => item.includes('> Error! Provided URL is invalid'))512 t.truthy(hasErrorMsg)513 hasErrorMsg = stdout.find(item => item.includes('> Error! 404: Not Found. Requested URL: https://raw.githubusercontent.com/frictionlessdata/test-data/master/files/other/sampl.csv'))514 t.truthy(hasErrorMsg)515})516// end of [Cat: basic csv]517// QA tests [Cat: different separators]518test('cat command - files with different separator', async t => {519 // Local files:520 let path_ = 'test/fixtures/test-data/files/csv/separators/semicolon.csv'521 let results = await runcli('cat', path_)522 let stdout = results.stdout.split('\n')523 let delimiterWasntRecognized = stdout.find(item => item.includes(';'))524 t.falsy(delimiterWasntRecognized)525 let hasCorrectPrint = stdout.find(item => item.includes('number'))526 t.truthy(hasCorrectPrint)527 path_ = 'test/fixtures/test-data/files/csv/separators/carets.csv'528 results = await runcli('cat', path_)529 stdout = results.stdout.split('\n')530 delimiterWasntRecognized = stdout.find(item => item.includes('^'))531 t.falsy(delimiterWasntRecognized)532 hasCorrectPrint = stdout.find(item => item.includes('number'))533 t.truthy(hasCorrectPrint)534 // Remote files:535 let url_ = 'https://raw.githubusercontent.com/frictionlessdata/test-data/master/files/csv/separators/semicolon.csv'536 results = await runcli('cat', url_)537 stdout = results.stdout.split('\n')538 delimiterWasntRecognized = stdout.find(item => item.includes(';'))539 t.falsy(delimiterWasntRecognized)540 hasCorrectPrint = stdout.find(item => item.includes('number'))541 t.truthy(hasCorrectPrint)542 url_ = 'https://raw.githubusercontent.com/frictionlessdata/test-data/master/files/csv/separators/carets.csv'543 results = await runcli('cat', url_)544 stdout = results.stdout.split('\n')545 delimiterWasntRecognized = stdout.find(item => item.includes('^'))546 t.falsy(delimiterWasntRecognized)547 hasCorrectPrint = stdout.find(item => item.includes('number'))548 t.truthy(hasCorrectPrint)549})550// end of [Cat: different separators]551// QA test [Cat: different encodings]552test.failing('cat command - different encodings', async t => {553 const path_ = 'test/fixtures/test-data/files/csv/encodings/iso8859.csv'554 let results = await runcli('cat', path_)555 let stdout = results.stdout.split('\n')556 let hasCorrectPrint = stdout.find(item => item.includes('Réunion'))557 t.truthy(hasCorrectPrint)558 const url_ = 'https://raw.githubusercontent.com/frictionlessdata/test-data/master/files/csv/encodings/western-macos-roman.csv'559 results = await runcli('cat', url_)560 stdout = results.stdout.split('\n')561 hasCorrectPrint = stdout.find(item => item.includes('Réunion'))562 t.truthy(hasCorrectPrint)563})564// end of [Cat: different encodings]565test('cat command - local tsv file', async t => {566 const path_= 'test/fixtures/test-data/files/csv/separators/tab.tsv'567 const results = await runcli('cat', path_)568 const stdout = results.stdout.split('\n')569 const hasCorrectPrint = stdout.find(item => item.includes('number'))570 t.truthy(hasCorrectPrint)571})572test('cat command - remote tsv file', async t => {573 const url_ = 'https://raw.githubusercontent.com/frictionlessdata/test-data/master/files/csv/separators/tab.tsv'574 const results = await runcli('cat', url_)575 const stdout = results.stdout.split('\n')576 const hasCorrectPrint = stdout.find(item => item.includes('number'))577 t.truthy(hasCorrectPrint)578})579test('cat command - inconsistent columns', async t => {580 const path_ = 'test/fixtures/test-data/files/csv/inconsistent-column-number.csv'581 const results = await runcli('cat', path_)582 const stdout = results.stdout.split('\n')583 const hasErrorMsg = stdout.find(item => item.includes('> Error! Number of columns is inconsistent on line 3'))584 t.truthy(hasErrorMsg)585})586test('cat command - remote excel file', async t => {587 const url_ = 'https://github.com/frictionlessdata/test-data/raw/master/files/excel/sample-1-sheet.xls'588 const results = await runcli('cat', url_)589 const stdout = results.stdout.split('\n')590 const hasCorrectPrint = stdout.find(item => item.includes('number'))591 t.truthy(hasCorrectPrint)592})593test('cat command - specific excel sheet', async t => {594 const path_ = 'test/fixtures/test-data/files/excel/sample-2-sheets.xlsx'595 // With sheet name:596 let results = await runcli('cat', path_, '--sheet=Sheet2')597 let stdout = results.stdout.split('\n')598 let hasHeaderFrom2ndSheet = stdout.find(item => item.includes('header4'))599 t.truthy(hasHeaderFrom2ndSheet)600 // With sheet index:601 results = await runcli('cat', path_, '--sheet=2')602 stdout = results.stdout.split('\n')603 hasHeaderFrom2ndSheet = stdout.find(item => item.includes('header4'))604 t.truthy(hasHeaderFrom2ndSheet)605 // When sheet doesn't exist:606 results = await runcli('cat', path_, '--sheet=3')607 stdout = results.stdout.split('\n')608 t.is(stdout[0], '> Error! Input source is empty or doesn\'t exist.')609})610module.exports = {611 runcli...
push.test.js
Source:push.test.js
1// These tests are run only on tagged commits2const test = require('ava')3const clipboardy = require('clipboardy')4const {runcli} = require('../cli.test.js')5// =====================6// DATA-CLI PUSH correct7// QA tests [pushing valid CSV file]8test.serial('push command succeeds with regular CSV file', async t => {9 const path_ = 'test/fixtures/test-data/files/csv/separators/comma.csv'10 const args = '--name=comma-separated'11 const result = await runcli('push', path_, args)12 const stdout = result.stdout.split('\n')13 const hasPublishedMessage = stdout.find(item => item.includes('your data is published!'))14 const hasURLtoShowcase = stdout.find(item => item.includes('https://datahub.io/test/comma-separated/v/'))15 t.truthy(hasPublishedMessage)16 t.truthy(hasURLtoShowcase)17 const whatsInClipboard = await clipboardy.read()18 t.true(whatsInClipboard.includes('https://datahub.io/test/comma-separated/v/'))19})20// end of [pushing valid CSV file]21test.serial('push --public', async t => {22 const path_ = 'test/fixtures/test-data/files/csv/separators/comma.csv'23 const args = ['--name=public-test', '--public', '--debug']24 const result = await runcli('push', path_, ...args)25 t.truthy(result.stdout.includes('"findability": "published"'))26})27// QA tests [pushing valid dataset from path]28test.serial('push command succeeds for valid dataset', async t => {29 const path_ = 'test/fixtures/test-data/packages/basic-csv'30 const result = await runcli('push', path_)31 const stdout = result.stdout.split('\n')32 const hasPublishedMessage = stdout.find(item => item.includes('your data is published!'))33 const hasURLtoShowcase = stdout.find(item => item.includes('https://datahub.io/test/basic-csv/v/'))34 t.truthy(hasPublishedMessage)35 t.truthy(hasURLtoShowcase)36 const whatsInClipboard = await clipboardy.read()37 t.true(whatsInClipboard.includes('https://datahub.io/test/basic-csv/v/'))38})39// end of [pushing valid dataset from path]40// QA tests [pushing valid dataset from working directory]41test.serial('pushing valid dataset from working directory', async t =>{42 const path_ = 'test/fixtures/test-data/packages/basic-csv'43 const usualWorkingDir = process.cwd()44 process.chdir(path_)45 console.log('Working directory changed: ' + process.cwd())46 // push test47 const result = await runcli('push')48 const stdout = result.stdout.split('\n')49 const hasPublishedMessage = stdout.find(item => item.includes('your data is published!'))50 const hasURLtoShowcase = stdout.find(item => item.includes('https://datahub.io/test/basic-csv/v/'))51 t.truthy(hasPublishedMessage)52 t.truthy(hasURLtoShowcase)53 const whatsInClipboard = await clipboardy.read()54 t.true(whatsInClipboard.includes('https://datahub.io/test/basic-csv/v/'))55 // change working dir to default, so other tests will not fail56 process.chdir(usualWorkingDir)57 console.log('Working directory restored: ' + process.cwd())58})59// QA tests [pushing multiple CSV files together] - should push only one file and show a WARNING message60// https://datahub.io/test/zero/v/8761test.serial.failing('pushing multiple CSV files Warning message', async t => {62 const path_ = 'test/fixtures/test-data/files/csv/separators/comma.csv'63 const path2_ = 'test/fixtures/test-data/files/csv/separators/colon.csv'64 const args = '--name=comma-separated'65 const result = await runcli('push', path_, path2_, args)66 const stdout = result.stdout.split('\n')67 const hasPublishedMessage = stdout.find(item => item.includes('your data is published!'))68 const hasURLtoShowcase = stdout.find(item => item.includes('https://datahub.io/test/comma-separated/v/'))69 const hasWarningMessage = stdout.find(item => item.includes(`Warning: pushing only the ${path_} file.`))70 t.truthy(hasPublishedMessage)71 t.truthy(hasURLtoShowcase)72 t.truthy(hasWarningMessage)73 const whatsInClipboard = await clipboardy.read()74 t.true(whatsInClipboard.includes('https://datahub.io/test/comma-separated/v/'))75})76// QA tests [pushing valid dataset with path to datapackage.json]77test.serial('push command succeeds for valid dataset with path to dp.json', async t => {78 const path_ = 'test/fixtures/test-data/packages/basic-csv/datapackage.json'79 const result = await runcli('push', path_)80 const stdout = result.stdout.split('\n')81 const hasPublishedMessage = stdout.find(item => item.includes('your data is published!'))82 const hasURLtoShowcase = stdout.find(item => item.includes('https://datahub.io/test/basic-csv/v/'))83 t.truthy(hasPublishedMessage)84 t.truthy(hasURLtoShowcase)85 const whatsInClipboard = await clipboardy.read()86 t.true(whatsInClipboard.includes('https://datahub.io/test/basic-csv/v/'))87})88// end of [pushing valid dataset with path to datapackage.json]89// QA tests [pushing valid CSV from URL]90test.serial('push command succeeds with regular CSV file from URL', async t => {91 const url_ = 'https://raw.githubusercontent.com/frictionlessdata/test-data/master/files/csv/separators/comma.csv'92 const args = '--name=comma-separated'93 const result = await runcli('push', url_, args)94 const stdout = result.stdout.split('\n')95 const hasPublishedMessage = stdout.find(item => item.includes('your data is published!'))96 const hasURLtoShowcase = stdout.find(item => item.includes('https://datahub.io/test/comma-separated/v/'))97 t.truthy(hasPublishedMessage)98 t.truthy(hasURLtoShowcase)99 const whatsInClipboard = await clipboardy.read()100 t.true(whatsInClipboard.includes('https://datahub.io/test/comma-separated/v/'))101})102// end of [pushing valid CSV from URL]103// ========================104// Invalid metadata or data105// QA tests [Push: Invalid datapackage.json]106test('push command fails with invalid JSON descriptor', async t => {107 let path_ = 'test/fixtures/test-data/packages/invalid-json-single-quotes'108 let result = await runcli('push', path_)109 let stdout = result.stdout.split('\n')110 let hasErrorMsg = stdout.find(item => item.includes('> Error! Unexpected token \' in JSON at position 27'))111 t.truthy(hasErrorMsg)112 // Suggests running validate command:113 const hasSuggestionMsg = stdout.find(item => item.includes('> \'data validate\' to check your data.'))114 t.truthy(hasSuggestionMsg)115 path_ = 'test/fixtures/test-data/packages/invalid-json-missing-comma'116 result = await runcli('push', path_)117 stdout = result.stdout.split('\n')118 hasErrorMsg = stdout.find(item => item.includes('> Error! Unexpected string in JSON at position 113'))119 t.truthy(hasErrorMsg)120})121// end of [Push: Invalid datapackage.json]122// QA tests [Push: Invalid descriptor metadata]123test('push command fails with descriptor validation error', async t => {124 let path_ = 'test/fixtures/test-data/packages/invalid-descriptor'125 let result = await runcli('push', path_)126 let stdout = result.stdout.split('\n')127 const hasErrorMsg = stdout.find(item => item.includes('Descriptor validation error:'))128 t.truthy(hasErrorMsg)129 let hasErrorDetails = stdout.find(item => item.includes('String does not match pattern: ^([-a-z0-9._/])+$'))130 t.truthy(hasErrorDetails)131 hasErrorDetails = stdout.find(item => item.includes('at \"/name\" in descriptor'))132 t.truthy(hasErrorDetails)133})134// end of [Push: Invalid descriptor metadata]135// QA tests [Push: Missing descriptor]136test('push command fails if descriptor is missing', async t => {137 let path_ = 'test/fixtures/test-data/packages'138 let result = await runcli('push', path_)139 let stdout = result.stdout.split('\n')140 const hasErrorMsg = stdout.find(item => item.includes('> Error! No datapackage.json at destination.'))141 t.truthy(hasErrorMsg)142 let suggestsToDoValidate = stdout.find(item => item.includes('data validate'))143 let suggestsToDoInit = stdout.find(item => item.includes('data init'))144 t.truthy(suggestsToDoValidate)145 t.truthy(suggestsToDoInit)146})147// end of [Push: Missing descriptor]148// QA tests [Push: pushing remote data package]149test('push command fails for remote datasets', async t => {150 let path_ = 'https://github.com/frictionlessdata/test-data/blob/master/packages/basic-csv/datapackage.json'151 let result = await runcli('push', path_)152 let stdout = result.stdout.split('\n')153 const hasErrorMsg = stdout.find(item => item.includes('Error: You can push only local datasets.'))154 t.truthy(hasErrorMsg)155})156// end of [Push: pushing remote data package]157// QA tests [Push: pushing valid dataset with remote resource]158test('push command succeeds for valid dataset with remote resource', async t => {159 let path_ = 'test/fixtures/test-data/packages/remote-csv'160 let result = await runcli('push', path_)161 let stdout = result.stdout.split('\n')162 const hasPublishedMessage = stdout.find(item => item.includes('your data is published!'))163 const hasURLtoShowcase = stdout.find(item => item.includes('https://datahub.io/test/remote-resource/v/'))164 t.truthy(hasPublishedMessage)165 t.truthy(hasURLtoShowcase)166 const whatsInClipboard = await clipboardy.read()167 t.true(whatsInClipboard.includes('https://datahub.io/test/remote-resource/v/'))168})169// end of [Push: pushing valid dataset with remote resource]170// QA tests [Pushing invalid CSV file (irrespective of schema)]171// Also includes [pushing invalid CSV from URL ]172test.failing('push command fails for invalid local CSV file', async t => {173 const path_ = 'test/fixtures/test-data/packages/invalid-data/extra-column.csv'174 const args = '--name=extra-column'175 const result = await runcli('push', path_, args)176 const stdout = result.stdout.split('\n')177 const hasErrorMsg = stdout.find(item => item.includes('> Error! Number of columns is inconsistent on line 2'))178 t.truthy(hasErrorMsg)179})180// end of [Pushing invalid CSV file (irrespective of schema)]181// QA tests [Pushing packaged invalid CSV file (irrespective of schema)]182test.serial('push command succeeds with packaged invalid CSV', async t => {183 const path_ = 'test/fixtures/test-data/packages/invalid-data'184 const result = await runcli('push', path_)185 const stdout = result.stdout.split('\n')186 const hasPublishedMessage = stdout.find(item => item.includes('your data is published!'))187 const hasURLtoShowcase = stdout.find(item => item.includes('https://datahub.io/test/basic-csv/v/'))188 t.truthy(hasPublishedMessage)189 t.truthy(hasURLtoShowcase)190 const whatsInClipboard = await clipboardy.read()191 t.true(whatsInClipboard.includes('https://datahub.io/test/basic-csv/v/'))192})193// end of [Pushing packaged invalid CSV file (irrespective of schema)]194// QA tests [Push non existing file]195test('push command fails for non-existing file', async t => {196 let path_ = 'non-existing.csv'197 let result = await runcli('push', path_)198 let stdout = result.stdout.split('\n')199 const hasErrorMsg = stdout.find(item => item.includes('> Error! ENOENT: no such file or directory, lstat \'non-existing.csv\''))200 t.truthy(hasErrorMsg)201})202// end of [Push non existing file]203// QA tests [pushing empty but correct files]204test('push command for empty files: no ext, html, txt, json', async t => {205 let path_ = 'test/fixtures/test-data/files/empty-files/empty'206 let args = '--name=empty-no-extension'207 let result = await runcli('push', path_, args)208 let stdout = result.stdout.split('\n')209 let hasPublishedMessage = stdout.find(item => item.includes('your data is published!'))210 let hasURLtoShowcase = stdout.find(item => item.includes('https://datahub.io/test/empty-no-extension/v/'))211 t.truthy(hasPublishedMessage)212 t.truthy(hasURLtoShowcase)213 path_ = 'test/fixtures/test-data/files/empty-files/empty.html'214 args = '--name=empty-html'215 result = await runcli('push', path_, args)216 stdout = result.stdout.split('\n')217 hasPublishedMessage = stdout.find(item => item.includes('your data is published!'))218 hasURLtoShowcase = stdout.find(item => item.includes('https://datahub.io/test/empty-html/v/'))219 t.truthy(hasPublishedMessage)220 t.truthy(hasURLtoShowcase)221 let whatsInClipboard = await clipboardy.read()222 t.true(whatsInClipboard.includes('https://datahub.io/test/empty-html/v/'))223 path_ = 'test/fixtures/test-data/files/empty-files/empty.txt'224 args = '--name=empty-txt'225 result = await runcli('push', path_, args)226 stdout = result.stdout.split('\n')227 hasPublishedMessage = stdout.find(item => item.includes('your data is published!'))228 hasURLtoShowcase = stdout.find(item => item.includes('https://datahub.io/test/empty-txt/v/'))229 t.truthy(hasPublishedMessage)230 t.truthy(hasURLtoShowcase)231 path_ = 'test/fixtures/test-data/files/empty-files/empty.json'232 args = '--name=empty-json'233 result = await runcli('push', path_, args)234 stdout = result.stdout.split('\n')235 hasPublishedMessage = stdout.find(item => item.includes('your data is published!'))236 hasURLtoShowcase = stdout.find(item => item.includes('https://datahub.io/test/empty-json/v/'))237 t.truthy(hasPublishedMessage)238 t.truthy(hasURLtoShowcase)239 whatsInClipboard = await clipboardy.read()240 t.true(whatsInClipboard.includes('https://datahub.io/test/empty-json/v/'))241})242test('push command fails for empty files tabular files such as csv,xls', async t => {243 let path_ = 'test/fixtures/test-data/files/empty-files/empty.csv'244 let args = '--name=empty-csv'245 let result = await runcli('push', path_, args)246 let stdout = result.stdout.split('\n')247 let hasErrorMsg = stdout.find(item => item.includes('tabular file is invalid: test/fixtures/test-data/files/empty-files/empty.csv'))248 t.truthy(hasErrorMsg)249 path_ = 'test/fixtures/test-data/files/empty-files/empty.xls'250 result = await runcli('push', path_, args)251 args = '--name=empty-xls'252 stdout = result.stdout.split('\n')253 hasErrorMsg = stdout.find(item => item.includes('You cannot push an empty sheet. Please, add some data and try again.'))254 t.truthy(hasErrorMsg)255})256// end of [pushing empty but correct files]257// QA tests [pushing 0 bytes files]258test('push command fails for zero byte files', async t => {259 let path_ = 'test/fixtures/test-data/files/zero-files/zero'260 let args = '--name=zero'261 let result = await runcli('push', path_, args)262 let stdout = result.stdout.split('\n')263 let hasPublishedMessage = stdout.find(item => item.includes('your data is published!'))264 let hasURLtoShowcase = stdout.find(item => item.includes('https://datahub.io/test/zero/v/'))265 t.truthy(hasPublishedMessage)266 t.truthy(hasURLtoShowcase)267 path_ = 'test/fixtures/test-data/files/zero-files/zero.csv'268 result = await runcli('push', path_, args)269 stdout = result.stdout.split('\n')270 t.true(stdout[0].includes('> Error! tabular file is invalid:'))271 path_ = 'test/fixtures/test-data/files/zero-files/zero.html'272 result = await runcli('push', path_, args)273 stdout = result.stdout.split('\n')274 hasPublishedMessage = stdout.find(item => item.includes('your data is published!'))275 hasURLtoShowcase = stdout.find(item => item.includes('https://datahub.io/test/zero/v/'))276 t.truthy(hasPublishedMessage)277 t.truthy(hasURLtoShowcase)278 path_ = 'test/fixtures/test-data/files/zero-files/zero.txt'279 result = await runcli('push', path_, args)280 stdout = result.stdout.split('\n')281 hasPublishedMessage = stdout.find(item => item.includes('your data is published!'))282 hasURLtoShowcase = stdout.find(item => item.includes('https://datahub.io/test/zero/v/'))283 t.truthy(hasPublishedMessage)284 t.truthy(hasURLtoShowcase)285 path_ = 'test/fixtures/test-data/files/zero-files/zero.json'286 result = await runcli('push', path_, args)287 stdout = result.stdout.split('\n')288 hasPublishedMessage = stdout.find(item => item.includes('your data is published!'))289 hasURLtoShowcase = stdout.find(item => item.includes('https://datahub.io/test/zero/v/'))290 t.truthy(hasPublishedMessage)291 t.truthy(hasURLtoShowcase)292 path_ = 'test/fixtures/test-data/files/zero-files/zero.xls'293 result = await runcli('push', path_, args)294 stdout = result.stdout.split('\n')295 let hasErrorMsg = stdout.find(item => item.includes('You can not push empty files, please add some data and try again'))296 t.truthy(hasErrorMsg)297})298// end of [pushing 0 bytes files]299// ==========300// Formatting301// QA tests [pushing valid CSV with force formatting wrong extention (from path and URl)]302test.serial('push command succeeds for CSV with wrong ext but force formatting', async t => {303 const path_ = 'test/fixtures/test-data/files/wrong-extension-files/comma.txt'304 let argName = '--name=comma-separated'305 let argFormat = '--format=csv'306 let result = await runcli('push', path_, argName, argFormat)307 let stdout = result.stdout.split('\n')308 let hasPublishedMessage = stdout.find(item => item.includes('your data is published!'))309 let hasURLtoShowcase = stdout.find(item => item.includes('https://datahub.io/test/comma-separated/v/'))310 t.truthy(hasPublishedMessage)311 t.truthy(hasURLtoShowcase)312 let whatsInClipboard = await clipboardy.read()313 t.true(whatsInClipboard.includes('https://datahub.io/test/comma-separated/v/'))314 const url_ = 'https://raw.githubusercontent.com/frictionlessdata/test-data/master/files/wrong-extension-files/comma.txt'315 result = await runcli('push', path_, argName, argFormat)316 stdout = result.stdout.split('\n')317 hasPublishedMessage = stdout.find(item => item.includes('your data is published!'))318 hasURLtoShowcase = stdout.find(item => item.includes('https://datahub.io/test/comma-separated/v/'))319 t.truthy(hasPublishedMessage)320 t.truthy(hasURLtoShowcase)321 whatsInClipboard = await clipboardy.read()322 t.true(whatsInClipboard.includes('https://datahub.io/test/comma-separated/v/'))323})324// end of [pushing valid CSV with force formatting wrong extention (from path and URl)]325// QA tests [pushing valid XLS and XLSX with force formatting]326test('push command succeeds for Excel with wrong ext but force formatting', async t => {327 let path_ = 'test/fixtures/test-data/files/wrong-extension-files/sample-1-sheet.txt'328 let argName = '--name=sample-excel-with-force-formatting'329 let argFormat = '--format=xls'330 let result = await runcli('push', path_, argName, argFormat)331 let stdout = result.stdout.split('\n')332 let hasPublishedMessage = stdout.find(item => item.includes('your data is published!'))333 let hasURLtoShowcase = stdout.find(item => item.includes('https://datahub.io/test/sample-excel-with-force-formatting/v/'))334 t.truthy(hasPublishedMessage)335 t.truthy(hasURLtoShowcase)336 let whatsInClipboard = await clipboardy.read()337 t.true(whatsInClipboard.includes('https://datahub.io/test/sample-excel-with-force-formatting/v/'))338 path_ = 'test/fixtures/test-data/files/wrong-extension-files/sample-1-sheet.pdf'339 argFormat = '--format=xlsx'340 result = await runcli('push', path_, argName, argFormat)341 stdout = result.stdout.split('\n')342 hasPublishedMessage = stdout.find(item => item.includes('your data is published!'))343 hasURLtoShowcase = stdout.find(item => item.includes('https://datahub.io/test/sample-excel-with-force-formatting/v/'))344 t.truthy(hasPublishedMessage)345 t.truthy(hasURLtoShowcase)346 whatsInClipboard = await clipboardy.read()347 t.true(whatsInClipboard.includes('https://datahub.io/test/sample-excel-with-force-formatting/v/'))348})349// end of [pushing valid XLS and XLSX with force formatting]350// QA test [pushing not CSV with force formatting]351test('push command fails for non-CSV with force formatting', async t => {352 let path_ = 'test/fixtures/test-data/files/excel/sample-1-sheet.xls'353 const argName = '--name=not-csv-as-csv'354 const argFormat = '--format=csv'355 let result = await runcli('push', path_, argName, argFormat)356 let stdout = result.stdout.split('\n')357 let hasExpectedErrorMsg = stdout.find(item => item.includes('> Error! tabular file is invalid'))358 t.truthy(hasExpectedErrorMsg)359 let url_ = 'https://raw.githubusercontent.com/frictionlessdata/test-data/master/files/excel/sample-1-sheet.xls'360 result = await runcli('push', path_, argName, argFormat)361 stdout = result.stdout.split('\n')362 hasExpectedErrorMsg = stdout.find(item => item.includes('> Error! tabular file is invalid'))363 t.truthy(hasExpectedErrorMsg)364 path_ = 'test/fixtures/test-data/files/excel/sample-1-sheet.xlsx'365 result = await runcli('push', path_, argName, argFormat)366 stdout = result.stdout.split('\n')367 hasExpectedErrorMsg = stdout.find(item => item.includes('> Error! tabular file is invalid'))368 t.truthy(hasExpectedErrorMsg)369 url_ = 'https://raw.githubusercontent.com/frictionlessdata/test-data/master/files/excel/sample-1-sheet.xlsx'370 result = await runcli('push', path_, argName, argFormat)371 stdout = result.stdout.split('\n')372 hasExpectedErrorMsg = stdout.find(item => item.includes('> Error! tabular file is invalid'))373 t.truthy(hasExpectedErrorMsg)374})375// end of [pushing not CSV with force formatting]376// QA test [pushing not CSV with force formatting (non tabular )]377test('push command fails for non-CSV (non-tabular) files with force formatting', async t => {378 let path_ = 'test/fixtures/test-data/files/other/sample.json'379 const argName = '--name=not-csv-as-csv'380 const argFormat = '--format=csv'381 let result = await runcli('push', path_, argName, argFormat)382 let stdout = result.stdout.split('\n')383 let hasExpectedErrorMsg = stdout.find(item => item.includes('> Error! tabular file is invalid'))384 t.truthy(hasExpectedErrorMsg)385 let url_ = 'https://raw.githubusercontent.com/frictionlessdata/test-data/master/files/other/sample.json'386 result = await runcli('push', path_, argName, argFormat)387 stdout = result.stdout.split('\n')388 hasExpectedErrorMsg = stdout.find(item => item.includes('> Error! tabular file is invalid'))389 t.truthy(hasExpectedErrorMsg)390})391// end of [pushing not CSV with force formatting (non tabular )]392// ===========393// Excel files394// QA test [pushing excel file with 1 sheet]395test.serial('push command succeeds for simple Excel with 1 sheet', async t => {396 let path_ = 'test/fixtures/test-data/files/excel/sample-1-sheet.xls'397 const argName = '--name=test-excel-1-sheet'398 let result = await runcli('push', path_, argName, '--debug')399 // Check what's printed in console while in debug mode, e.g., if schema is included:400 let hasSchemaForFirstSheet = result.stdout.includes('"name": "number"')401 t.truthy(hasSchemaForFirstSheet)402 let hasPublishedMessage = result.stdout.includes('your data is published!')403 let hasURLtoShowcase = result.stdout.includes('https://datahub.io/test/test-excel-1-sheet/v/')404 t.truthy(hasPublishedMessage)405 t.truthy(hasURLtoShowcase)406 let whatsInClipboard = await clipboardy.read()407 t.true(whatsInClipboard.includes('https://datahub.io/test/test-excel-1-sheet/v/'))408 path_ = 'test/fixtures/test-data/files/excel/sample-1-sheet.xlsx'409 result = await runcli('push', path_, argName, '--debug')410 hasSchemaForFirstSheet = result.stdout.includes('"name": "number"')411 t.truthy(hasSchemaForFirstSheet)412 hasPublishedMessage = result.stdout.includes('your data is published!')413 hasURLtoShowcase = result.stdout.includes('https://datahub.io/test/test-excel-1-sheet/v/')414 t.truthy(hasPublishedMessage)415 t.truthy(hasURLtoShowcase)416 whatsInClipboard = await clipboardy.read()417 t.true(whatsInClipboard.includes('https://datahub.io/test/test-excel-1-sheet/v/'))418})419// end of [pushing excel file with 1 sheet]420// QA test [pushing excel file with selected sheets]421// also includes:422// [pushing excel file with selected non existing sheet]423// [pushing excel file with all sheets]424// [pushing excel file with list of sheets]425test.serial('push command succeeds for Excel with selected sheet', async t => {426 let path_ = 'test/fixtures/test-data/files/excel/sample-2-sheets.xls'427 const argName = '--name=test-excel-2-sheets'428 let argSheets = '--sheets=2'429 let result = await runcli('push', path_, argName, argSheets, '--debug')430 // Check what's printed in console while in debug mode, e.g., if schema is included:431 let hasSchemaForSecondSheet = result.stdout.includes('"name": "header4"')432 t.truthy(hasSchemaForSecondSheet)433 let hasPublishedMessage = result.stdout.includes('your data is published!')434 let hasURLtoShowcase = result.stdout.includes('https://datahub.io/test/test-excel-2-sheets/v/')435 t.truthy(hasPublishedMessage)436 t.truthy(hasURLtoShowcase)437 let whatsInClipboard = await clipboardy.read()438 t.true(whatsInClipboard.includes('https://datahub.io/test/test-excel-2-sheets/v/'))439 path_ = 'test/fixtures/test-data/files/excel/sample-2-sheets.xlsx'440 result = await runcli('push', path_, argName, argSheets, '--debug')441 // Check what's printed in console while in debug mode, e.g., if schema is included:442 hasSchemaForSecondSheet = result.stdout.includes('"name": "header4"')443 t.truthy(hasSchemaForSecondSheet)444 hasPublishedMessage = result.stdout.includes('your data is published!')445 hasURLtoShowcase = result.stdout.includes('https://datahub.io/test/test-excel-2-sheets/v/')446 t.truthy(hasPublishedMessage)447 t.truthy(hasURLtoShowcase)448 whatsInClipboard = await clipboardy.read()449 t.true(whatsInClipboard.includes('https://datahub.io/test/test-excel-2-sheets/v/'))450 argSheets = '--sheets=5'451 result = await runcli('push', path_, argName, argSheets, '--debug')452 let hasErrorMsg = result.stdout.includes('Error! sheet index 5 is out of range')453 t.truthy(hasErrorMsg)454 argSheets = '--sheets=all'455 result = await runcli('push', path_, argName, argSheets, '--debug')456 let hasSchemaForFirstSheet = result.stdout.includes('"name": "header1"')457 hasSchemaForSecondSheet = result.stdout.includes('"name": "header4"')458 t.truthy(hasSchemaForFirstSheet)459 t.truthy(hasSchemaForSecondSheet)460 argSheets = '--sheets=1,2'461 result = await runcli('push', path_, argName, argSheets, '--debug')462 hasSchemaForFirstSheet = result.stdout.includes('"name": "header1"')463 hasSchemaForSecondSheet = result.stdout.includes('"name": "header4"')464 t.truthy(hasSchemaForFirstSheet)465 t.truthy(hasSchemaForSecondSheet)466})467// end of [pushing excel file with selected sheets]468test('push command fails for resources with invalid URL as path', async t => {469 const url_ = 'https://github.com/datasets/testtest'470 const argName = '--name=test'471 let result = await runcli('push', url_, argName)472 let stdout = result.stdout.split('\n')473 let hasErrorMsg = stdout.find(item => item.includes('> Error! Invalid URL. 404 Not Found: https://github.com/datasets/testtest'))474 t.truthy(hasErrorMsg)475 // Pushing a dataset with remote resource:476 const path_ = 'test/fixtures/test-data/packages/invalid-remote-path/'477 result = await runcli('push', path_, argName)478 stdout = result.stdout.split('\n')479 hasErrorMsg = stdout.find(item => item.includes('> Error! '))480 t.truthy(hasErrorMsg)...
publish_test.js
Source:publish_test.js
...83 });84 85 it("should warn if the package.json is missing", function(done){86 fs.unlinkSync(packagePath);87 runCLI("publish", ["major"], function(err, stdout, stderr){88 expect(stderr).to.match(/ERROR: Could not find package.json/);89 done();90 });91 });92 it("should fail if the package.json cannot be parsed", function(done){93 fs.writeFileSync(packagePath, packageJson + "!@#!@#", "utf8");94 runCLI("publish", ["major"], function(err, stdout, stderr){95 expect(stderr).to.match(/ERROR: Could not parse package.json/);96 done();97 });98 });99 it("should fail if the name in the package.json is missing", function(done){100 fs.writeFileSync(packagePath, packageJson.replace('"name": "c9.ide.example",', ''));101 runCLI("publish", ["major"], function(err, stdout, stderr){102 expect(stderr).to.match(/ERROR: Missing name property in package.json/);103 done();104 });105 });106 it("should fail if the name in the package.json is not equal to the directory", function(done){107 fs.writeFileSync(packagePath, packageJson.replace('"name": "c9.ide.example"', '"name": "wrongname"'));108 runCLI("publish", ["major"], function(err, stdout, stderr){109 expect(stderr).to.match(/WARNING: The name property in package.json is not equal to the directory name/);110 done();111 });112 });113 it("should fail if the description in the package.json is missing", function(done){114 fs.writeFileSync(packagePath, packageJson.replace(/"description":.*/, ''));115 runCLI("publish", ["major"], function(err, stdout, stderr){116 expect(stderr).to.match(/ERROR: Missing description property in package.json/);117 done();118 });119 });120 it("should fail if the repository in the package.json is missing", function(done){121 fs.writeFileSync(packagePath, packageJson.replace(/"repository[\s\S]*?\},/, ""));122 runCLI("publish", ["major"], function(err, stdout, stderr){123 expect(stderr).to.match(/ERROR: Missing repository property in package.json/);124 done();125 });126 });127 it("should fail if the category length is < 1 in the package.json is missing", function(done){128 fs.writeFileSync(packagePath, packageJson.replace(/"categories[\s\S]*?\],/, ""));129 runCLI("publish", ["major"], function(err, stdout, stderr){130 expect(stderr).to.match(/ERROR: At least one category is required in package.json/);131 done();132 });133 });134 it("should warn if a plugin is not listed in the package.json", function(done){135 fs.writeFileSync(packagePath, packageJson.replace('"example": {}', ''));136 runCLI("publish", ["major"], function(err, stdout, stderr){137 expect(stderr).to.match(/WARNING: Plugin 'example.js' is not listed in package.json./);138 done();139 });140 });141 it("should warn if the README.md is missing", function(done){142 fs.writeFileSync(packagePath, packageJson);143 fs.unlink(readmePath);144 runCLI("publish", ["major"], function(err, stdout, stderr){145 expect(stderr).to.match(/WARNING: README.md is missing./);146 done();147 });148 });149 it("should publish when using force and increase the patch version", function(done){150 var strJson = packageJson.replace(/"version": "[\d\.]+"/, '"version": "0.0.0"');151 fs.writeFileSync(packagePath, strJson);152 runCLI("publish", ["patch", "--force"], function(err, stdout, stderr){153 assert(!err, err);154 expect(stdout).to.match(/Succesfully published version 0.0.1/);155 156 runCLI("list", ["--json"], function(err, stdout, stderr){157 assert(!err, err);158 159 json.latest = "0.0.1";160 161 var list = JSON.parse(stdout);162 if (!list.some(function(item){163 if (item.name == "c9.ide.example") {164 expect(item).deep.equal(json);165 return true;166 }167 })) throw new Error("Could not find plugin in list");168 169 done();170 });171 });172 });173 it("should increase the minor version", function(done){174 fs.writeFileSync(readmePath, readmeMD);175 runCLI("publish", ["minor"], function(err, stdout, stderr){176 assert(!err, err);177 expect(stdout).to.match(/Succesfully published version 0.1.0/);178 179 runCLI("list", ["--json"], function(err, stdout, stderr){180 assert(!err, err);181 182 json.latest = "0.1.0";183 184 var list = JSON.parse(stdout);185 if (!list.some(function(item){186 if (item.name == "c9.ide.example") {187 expect(item).deep.equal(json);188 return true;189 }190 })) throw new Error("Could not find plugin in list");191 192 done();193 });194 });195 });196 it("should increase the major version", function(done){197 runCLI("publish", ["major"], function(err, stdout, stderr){198 assert(!err, err);199 expect(stdout).to.match(/Succesfully published version 1.0.0/);200 201 runCLI("list", ["--json"], function(err, stdout, stderr){202 assert(!err, err);203 204 json.latest = "1.0.0";205 206 var list = JSON.parse(stdout);207 if (!list.some(function(item){208 if (item.name == "c9.ide.example") {209 expect(item).deep.equal(json);210 return true;211 }212 })) throw new Error("Could not find plugin in list");213 214 done();215 });216 });217 });218 it("should hide the package when it is unpublished", function(done){219 runCLI("unpublish", [], function(err, stdout, stderr){220 assert(!err, err);221 expect(stdout).to.match(/Succesfully disabled package/);222 223 runCLI("list", ["--json"], function(err, stdout, stderr){224 assert(!err, err);225 expect(stdout).to.not.match(/c9\.ide\.example/);226 done();227 });228 });229 });230 });231 232 describe("install and remove (uninstall)", function() {233 var pluginDir = join(process.env.HOME, ".c9/plugins/c9.ide.example");234 235 // Lets make sure there is at least one package in the database236 before(function(done){237 // Create git repo that contains a plugin we'll use to test238 var p = child.spawn(join(__dirname, "publish_test.git.sh"));239 240 if (VERBOSE) {241 p.stdout.on("data", function(c){242 process.stdout.write(c.toString("utf8"));243 });244 p.stderr.on("data", function(c){245 process.stderr.write(c.toString("utf8"));246 });247 }248 p.on("close", function(code){249 if (code) 250 return done(new Error("Git setup failed"));251 252 runCLI("publish", ["10.0.0"], function(err, stdout, stderr){253 done();254 });255 });256 });257 258 it("should install a package locally", function(done){259 runCLI("install", ["--local", "c9.ide.example"], function(err, stdout, stderr){260 expect(stdout).to.match(/Succesfully installed c9.ide.example@10.0.0/);261 expect(fs.existsSync(pluginDir)).ok;262 done();263 });264 });265 it("should warn if a package is already installed", function(done){266 runCLI("install", ["--debug", "c9.ide.example"], function(err, stdout, stderr){267 expect(stderr).to.match(/WARNING: Directory not empty/);268 done();269 });270 });271 it("should install a package in debug mode", function(done){272 runCLI("install", ["--force", "--debug", "c9.ide.example"], function(err, stdout, stderr){273 expect(stdout).to.match(/Succesfully installed c9.ide.example/);274 expect(fs.existsSync(join(pluginDir, "/.git"))).ok;275 done();276 });277 });278 it("should install a package via the database", function(done){279 runCLI("install", ["c9.ide.example"], function(err, stdout, stderr){280 expect(stdout).to.match(/Succesfully installed c9.ide.example/);281 282 // @TODO check if it's actually in the database - add list --own to cli283 284 done();285 });286 });287 it("should remove a package locally", function(done){288 runCLI("remove", ["--local", "c9.ide.example"], function(err, stdout, stderr){289 expect(stdout).to.match(/Succesfully removed c9.ide.example/);290 expect(fs.existsSync(pluginDir)).not.ok;291 done();292 });293 });294 it("should remove a from the database", function(done){295 runCLI("remove", ["c9.ide.example"], function(err, stdout, stderr){296 expect(stdout).to.match(/Succesfully removed c9.ide.example/);297 298 // @TODO check if it's actually in the database - add list --own to cli299 300 done();301 });302 });303 });304});305function runCLI(command, options, callback){306 var env = Object.create(process.env);307 env["NODE_TLS_REJECT_UNAUTHORIZED"] = 0;308 env["C9_APIHOST"] = HOST;309 env["C9_PID"] = PID;310 env["C9_TEST_AUTH"] = USERNAME + ":" + PASSWORD;311 env["C9_TEST_MODE"] = 1;312 313 options.push("--verbose");314 var p = child.spawn(join(__dirname, "../../bin/c9"), [command].concat(options), {315 cwd: BASE,316 env: env317 });318 319 if (VERBOSE)...
runCli.js
Source:runCli.js
1import { join } from 'path';2import expect, { createSpy, spyOn } from 'expect';3import stripAnsi from 'strip-ansi';4import { consoleMockWrapper } from '../utils';5import runCli from '../../src/cli/runCli';6import defaultLog from '../../src/log/default';7describe('cli', () => {8 describe('runCli', () => {9 const spy = createSpy();10 const logError = spyOn(defaultLog.large, 'error').andThrow();11 const commands = {12 test: {13 command: spy,14 arguments: [{15 name: 'artifact',16 }],17 options: [{18 name: 'list',19 }],20 settings: true,21 },22 };23 let logWarningSpy;24 beforeEach(() => {25 logWarningSpy = spyOn(require('../../src/log/default/large').default, 'warn'); // eslint-disable-line26 });27 afterEach(() => {28 spy.reset();29 logWarningSpy.restore();30 });31 after(() => {32 expect.restoreSpies();33 });34 it('should return version when requested', () =>35 consoleMockWrapper((log) => {36 runCli({37 info: { version: '1.0.1' },38 argv: ['node', '/some/path', '-v'],39 });40 expect(log.calls[0].arguments[0]).toBe('1.0.1');41 runCli({42 info: { version: '1.0.1' },43 argv: ['node', '/some/path', '--version'],44 });45 expect(log.calls[1].arguments[0]).toBe('1.0.1');46 runCli({47 argv: ['node', '/some/path', '--version'],48 });49 expect(log.calls[2].arguments[0]).toBe('Unknown');50 })51 );52 it('should show general information if no command or version is given', () =>53 consoleMockWrapper((log) => {54 runCli({55 info: { version: '1.0.1' },56 argv: ['node', '/some/path'],57 });58 expect(log.calls[0].arguments[0]).toInclude('No commands available.');59 })60 );61 it('should show information if command is invalid', () =>62 consoleMockWrapper(() => {63 expect(() => runCli({64 info: { version: '1.0.1', name: 'roc-test' },65 commands,66 argv: ['node', '/some/path', 'command'],67 })).toThrow();68 expect(stripAnsi(logError.calls[0].arguments[0])).toInclude('Did not understand command');69 })70 );71 it('should show help info when requested', () =>72 consoleMockWrapper((log) => {73 runCli({74 info: { version: '1.0.1', name: 'roc-test' },75 commands,76 argv: ['node', '/some/path', 'test', '-h'],77 });78 expect(log.calls[0].arguments[0]).toInclude('Usage: roc-test test');79 })80 );81 it('should call command function', () =>82 consoleMockWrapper(() => {83 runCli({84 info: { version: '1.0.1', name: 'roc-test' },85 commands,86 argv: ['node', '/some/path', 'test'],87 });88 expect(spy.calls[0].arguments[0].info)89 .toEqual({ version: '1.0.1', name: 'roc-test' });90 expect(spy.calls[0].arguments[0].arguments)91 .toEqual({ managed: { artifact: undefined }, unmanaged: [] });92 expect(spy.calls[0].arguments[0].options)93 .toEqual({ managed: { list: undefined }, unmanaged: {} });94 })95 );96 it('should call relay debug option', () =>97 consoleMockWrapper(() => {98 runCli({99 info: { version: '1.0.1', name: 'roc-test' },100 commands,101 argv: ['node', '/some/path', 'test', '--verbose'],102 });103 expect(spy.calls[0].arguments[0].context.verbose)104 .toBe(true);105 })106 );107 it('should parse argument', () => {108 runCli({109 info: { version: '1.0.1', name: 'roc-test' },110 commands,111 argv: [112 'node',113 '/some/path',114 'test',115 `--directory=${join(__dirname, 'fixtures', 'runCli', 'projects', 'a')}`,116 '--group1-port=8080',117 ],118 });119 expect(spy.calls[0].arguments[0].context.config.settings)120 .toEqual({121 group1: {122 port: 8080,123 },124 });125 });126 });...
cli.spec.js
Source:cli.spec.js
1const { describe, it, expect } = require('@jest/globals')2const { join } = require('path')3const pkgDir = require('pkg-dir')4const { execFile } = require('child_process')5const packageRootDirectory = pkgDir.sync(__dirname)6function runCli(argArray) {7 return new Promise((resolve) => {8 const child = execFile(9 'node',10 [join(packageRootDirectory, 'src', 'main.js'), ...argArray],11 (error, stdout, stderr) => {12 resolve({13 exitCode: child.exitCode,14 error,15 stdout,16 stderr17 })18 }19 )20 })21}22describe(`cli`, function () {23 describe(`check command`, () => {24 it('exits with code 0 on success (json format)', async () => {25 const result = await runCli([26 'check',27 join(packageRootDirectory, 'test', 'fixtures', 'plugin-bundle-size', 'bundle.js'),28 '--config',29 join(packageRootDirectory, 'test', 'fixtures', 'plugin-bundle-size', '.bvrc.json')30 ])31 expect(result.stdout).not.toMatch(/E\d\d\d/)32 expect(result.exitCode).toEqual(0)33 })34 it('outputs a valid TAP report', async () => {35 const result = await runCli([36 'check',37 join(packageRootDirectory, 'test', 'fixtures', 'tap-report', '*.js'),38 '--config',39 join(packageRootDirectory, 'test', 'fixtures', 'tap-report', '.bvrc.json')40 ])41 expect(result.stdout).toContain('# tests 3')42 expect(result.stdout).toContain('# pass 2')43 expect(result.stdout).toContain('# fail 1')44 expect(result.stdout).toContain('1..3')45 expect(result.stdout).toContain('"i-am-a-long-file.js" contains more than 8 characters')46 expect(result.exitCode).not.toEqual(0)47 })48 it('exits with non-zero exit code if config cannot be found', async () => {49 const result = await runCli(['check', '*.js'])50 expect(result.stderr).toMatch(/E003/)51 expect(result.exitCode).not.toEqual(0)52 })53 it('exits with non-zero exit code if config cannot be loaded', async () => {54 const result = await runCli([55 'check',56 '*.js',57 '--config',58 join(packageRootDirectory, 'test', 'fixtures', 'invalid-configs', 'no-existent-config.json')59 ])60 expect(result.stderr).toMatch(/E002/)61 expect(result.exitCode).not.toEqual(0)62 })63 it('exits with non-zero exit code if provided config does not match schema', async () => {64 const result = await runCli([65 'check',66 '*.js',67 '--config',68 join(packageRootDirectory, 'test', 'fixtures', 'invalid-configs', '.bvrc.json')69 ])70 expect(result.stderr).toMatch(/E001/)71 expect(result.exitCode).not.toEqual(0)72 })73 it('exits with non-zero exit code if some plugin cannot be loaded', async () => {74 const result = await runCli([75 'check',76 '*.js',77 '--config',78 join(79 packageRootDirectory,80 'test',81 'fixtures',82 'invalid-configs',83 'non-existent-plugin.bvrc.json'84 )85 ])86 expect(result.stderr).toMatch(/E004/)87 expect(result.exitCode).not.toEqual(0)88 })89 })90 describe('plugin-bundle-size', () => {91 it('exits with code 0 on success after running plugin-bundle-size', async () => {92 const result = await runCli([93 'check',94 join(95 packageRootDirectory,96 'test',97 'fixtures',98 'plugin-bundle-size',99 'sample-size-files',100 'test'101 ),102 '--config',103 join(packageRootDirectory, 'test', 'fixtures', 'plugin-bundle-size', '.bundleSizePass.json')104 ])105 expect(result.exitCode).toEqual(0)106 })107 it('exits with code 1 on fail after running plugin-bundle-size', async () => {108 const result = await runCli([109 'check',110 join(111 packageRootDirectory,112 'test',113 'fixtures',114 'plugin-bundle-size',115 'sample-size-files',116 'test'117 ),118 '--config',119 join(packageRootDirectory, 'test', 'fixtures', 'plugin-bundle-size', '.bundleSizeFail.json')120 ])121 expect(result.exitCode).toEqual(1)122 })123 it('exits with code 0 on success after running plugin-bundle-size, maxSize option expressed as a number', async () => {124 const result = await runCli([125 'check',126 join(127 packageRootDirectory,128 'test',129 'fixtures',130 'plugin-bundle-size',131 'sample-size-files',132 'test'133 ),134 '--config',135 join(packageRootDirectory, 'test', 'fixtures', 'plugin-bundle-size', '.bundleSizeNum.json')136 ])137 expect(result.exitCode).toEqual(0)138 })139 })...
cli-tests.js
Source:cli-tests.js
1jest.autoMockOff();2jest.setTimeout(25000);3const { spawn } = require("child_process");4const path = require("path");5const fs = require("fs");6const promisify = require("util.promisify");7const rimraf = require("rimraf");8const minifyCli = require.resolve("../bin/minify");9const readFileAsync = promisify(fs.readFile);10const readFile = file => readFileAsync(file).then(out => out.toString());11const unlink = promisify(rimraf);12function runCli(args = [], stdin) {13 return new Promise((resolve, reject) => {14 const child = spawn("node", [minifyCli, ...args], {15 stdio: [stdin ? "pipe" : "inherit", "pipe", "pipe"],16 shell: true17 });18 if (stdin) {19 child.stdin.end(stdin);20 }21 let stdout = "";22 let stderr = "";23 child.stdout.on("data", data => (stdout += data));24 child.stderr.on("data", data => (stderr += data));25 child.on(26 "close",27 code =>28 code === 0 ? resolve({ stdout, stderr }) : reject({ code, stderr })29 );30 });31}32let tempSource = `33function foo() {34 const bar = x(1);35 const baz = y(2);36 return z(bar, baz);37}38`;39const sampleInputFile = path.join(__dirname, "fixtures/out-file/foo.js");40const sampleInputDir = path.join(__dirname, "fixtures/out-dir/a");41const sampleInputModule = path.join(__dirname, "fixtures/module/mod.js");42const tempOutFile = path.join(__dirname, "fixtures/out-file/foo.min.js");43const tempOutDir = path.join(__dirname, "fixtures/out-dir/min");44const tempOutDirFile = path.join(__dirname, "fixtures/out-dir/min/foo.js");45describe("babel-minify CLI", () => {46 afterEach(async () => {47 await unlink(tempOutDir);48 await unlink(tempOutFile);49 });50 it("should show help for --help", () => {51 return expect(runCli(["--help"])).resolves.toBeDefined();52 });53 it("should show version for --version", () => {54 const { version } = require("../package");55 return expect(56 runCli(["--version"]).then(({ stdout }) => stdout.trim())57 ).resolves.toBe(version);58 });59 it("should throw on all invalid options", () => {60 return expect(runCli(["--foo", "--bar"])).rejects.toMatchSnapshot();61 });62 it("stdin + stdout", () => {63 return expect(64 runCli(["--mangle.topLevel"], tempSource)65 ).resolves.toMatchSnapshot();66 });67 it("stdin + outFile", async () => {68 await runCli(["--out-file", tempOutFile], tempSource);69 expect(await readFile(tempOutFile)).toMatchSnapshot();70 });71 it("input file + stdout", async () => {72 return expect(runCli([sampleInputFile])).resolves.toMatchSnapshot();73 });74 it("input file + outFile", async () => {75 await runCli([sampleInputFile, "--out-file", tempOutFile]);76 expect(await readFile(tempOutFile)).toMatchSnapshot();77 });78 it("input file + outDir", async () => {79 await runCli([sampleInputFile, "--out-dir", tempOutDir]);80 expect(await readFile(tempOutDirFile)).toMatchSnapshot();81 });82 it("input dir + outdir", async () => {83 await runCli([sampleInputDir, "--out-dir", tempOutDir]);84 expect(await readFile(tempOutDirFile)).toMatchSnapshot();85 });86 it("should handle source type", async () => {87 return expect(runCli([sampleInputModule, "--sourceType module"])).resolves;88 });89 it("should handle comments", async () => {90 return expect(91 Promise.all([92 runCli([sampleInputModule, "--sourceType module", "--comments false"]),93 runCli([sampleInputModule, "--sourceType module", "--comments true"])94 ])95 ).resolves.toMatchSnapshot();96 });...
Gulpfile.js
Source:Gulpfile.js
1const {series, parallel} = require('gulp');2const {spawn} = require('child_process');3const fs = require('fs').promises;4const path = require('path');5const del = require('del');6const args = require('yargs').argv;7const webpack = require('webpack');8const WebpackDevServer = require('webpack-dev-server');9const webpackConfig = require('./webpack.renderer.config');10const log = (x) => console.log(x);11const BUILD_PATH = path.join(__dirname, '.electron');12const runCli = (cmd, cb) => {13 const [arg1, ...arg2] = cmd.split(' ');14 const proc = spawn(arg1, arg2, {15 stdio: 'inherit',16 shell: true,17 });18 proc.on('exit', cb);19};20function clean() {21 return del([`${BUILD_PATH}/**/*`]);22}23function renderer(cb) {24 runCli('webpack --config webpack.renderer.config.js', cb);25}26function main(cb) {27 runCli('webpack --config ./webpack.main.config.js', cb);28}29async function packageJson(cb) {30 let package = JSON.parse(31 await fs.readFile(path.join(__dirname, 'package.json')),32 );33 let {34 name,35 version,36 private,37 author,38 description,39 dependencies,40 optionalDependencies,41 } = package;42 let nativeDeps = require('./nativeDeps').default;43 let natives = {};44 let searchDeps = {45 ...dependencies,46 ...optionalDependencies,47 };48 nativeDeps.map((k) => {49 natives[k] = searchDeps[k];50 });51 let newPackage = {52 name,53 version,54 private,55 author,56 description,57 // dependencies: natives,58 // agora_electron: {59 // electron_version: '5.0.8',60 // prebuilt: true,61 // },62 };63 await fs.writeFile(64 path.join(BUILD_PATH, 'package.json'),65 JSON.stringify(newPackage, null, 2),66 );67 return;68}69function build(cb) {70 runCli('electron-builder build --config ./electron-builder.js', cb);71}72function electronDevServer(cb) {73 const config = webpack(webpackConfig);74 new WebpackDevServer(config, {75 hot: true,76 }).listen(webpackConfig.devServer.port, 'localhost', (err) => {77 if (err) {78 console.error(err);79 } else {80 cb();81 }82 });83}84function directory(){85 return fs.mkdir(BUILD_PATH, {recursive: true});86}87function mainDev(cb) {88 runCli('webpack --config ./webpack.main.config.js', cb);89}90function start(cb) {91 runCli('electron .', cb);92}93module.exports.build = series(94 clean,95 directory,96 parallel(renderer, main, packageJson),97 build,98);...
LambdaTest’s Jest Testing Tutorial covers step-by-step guides around Jest with code examples to help you be proficient with the Jest framework. The Jest tutorial has chapters to help you learn right from the basics of Jest framework to code-based tutorials around testing react apps with Jest, perform snapshot testing, import ES modules and more.
|<p>it('check_object_of_Car', () => {</p><p>
expect(newCar()).toBeInstanceOf(Car);</p><p>
});</p>|
| :- |
Get 100 minutes of automation test minutes FREE!!