Best JavaScript code snippet using cypress
migrator-spec.js
Source:migrator-spec.js
1'use strict';2const {expect} = require('chai');3const sinon = require('sinon');4const proxyquire = require('proxyquire');5const configStub = require('../../utils/config-stub');6const errors = require('../../../lib/errors');7const migratePath = '../../../lib/tasks/migrator';8describe('Unit: Tasks > Migrator', function () {9 describe('migrate', function () {10 it('runs direct command if useGhostUser returns false', function () {11 const config = configStub();12 const execaStub = sinon.stub().resolves();13 const useGhostUserStub = sinon.stub().returns(false);14 const migrator = proxyquire(migratePath, {15 execa: execaStub,16 '../utils/use-ghost-user': {shouldUseGhostUser: useGhostUserStub}17 });18 const sudoStub = sinon.stub().resolves();19 return migrator.migrate({instance: {config, dir: '/some-dir'}, ui: {sudo: sudoStub}}).then(() => {20 expect(useGhostUserStub.calledOnce).to.be.true;21 expect(useGhostUserStub.args[0][0]).to.equal('/some-dir/content');22 expect(execaStub.calledOnce).to.be.true;23 expect(sudoStub.called).to.be.false;24 });25 });26 it('runs sudo command if useGhostUser returns true', function () {27 const config = configStub();28 const execaStub = sinon.stub().resolves();29 const useGhostUserStub = sinon.stub().returns(true);30 const migrator = proxyquire(migratePath, {31 execa: execaStub,32 '../utils/use-ghost-user': {shouldUseGhostUser: useGhostUserStub}33 });34 const sudoStub = sinon.stub().resolves();35 return migrator.migrate({instance: {config, dir: '/some-dir'}, ui: {sudo: sudoStub}}).then(() => {36 expect(useGhostUserStub.calledOnce).to.be.true;37 expect(useGhostUserStub.args[0][0]).to.equal('/some-dir/content');38 expect(execaStub.calledOnce).to.be.false;39 expect(sudoStub.called).to.be.true;40 });41 });42 it('throws config error with db host if database not found', function () {43 const config = configStub();44 const execaStub = sinon.stub().returns(Promise.reject({stderr: 'CODE: ENOTFOUND'}));45 const useGhostUserStub = sinon.stub().returns(false);46 const migrator = proxyquire(migratePath, {47 execa: execaStub,48 '../utils/use-ghost-user': {shouldUseGhostUser: useGhostUserStub}49 });50 return migrator.migrate({instance: {config, dir: '/some-dir', system: {environment: 'testing'}}}).then(() => {51 expect(false, 'error should have been thrown').to.be.true;52 }).catch((error) => {53 expect(error).to.be.an.instanceof(errors.ConfigError);54 expect(error.options.config).to.have.key('database.connection.host');55 });56 });57 it('throws config error with db user if access denied error', function () {58 const config = configStub();59 const execaStub = sinon.stub().returns(Promise.reject({stderr: 'CODE: ER_ACCESS_DENIED_ERROR'}));60 const useGhostUserStub = sinon.stub().returns(false);61 const migrator = proxyquire(migratePath, {62 execa: execaStub,63 '../utils/use-ghost-user': {shouldUseGhostUser: useGhostUserStub}64 });65 return migrator.migrate({instance: {config, dir: '/some-dir', system: {environment: 'testing'}}}).then(() => {66 expect(false, 'error should have been thrown').to.be.true;67 }).catch((error) => {68 expect(error).to.be.an.instanceof(errors.ConfigError);69 expect(error.options.config).to.have.all.keys('database.connection.user', 'database.connection.password');70 });71 });72 it('throws system error if sqlite3 error is thrown by knex', function () {73 const config = configStub();74 const execaStub = sinon.stub().returns(Promise.reject({stdout: 'Knex: run\n$ npm install sqlite3 --save\nError:'}));75 const useGhostUserStub = sinon.stub().returns(false);76 const migrator = proxyquire(migratePath, {77 execa: execaStub,78 '../utils/use-ghost-user': {shouldUseGhostUser: useGhostUserStub}79 });80 return migrator.migrate({instance: {config, dir: '/some-dir', system: {environment: 'testing'}}}).then(() => {81 expect(false, 'error should have been thrown').to.be.true;82 }).catch((error) => {83 expect(error).to.be.an.instanceof(errors.SystemError);84 expect(error.message).to.match(/sqlite3 did not install properly/);85 });86 });87 it('error on `ghost update`', function () {88 const originalArgv = process.argv;89 process.argv = ['node', 'ghost', 'update'];90 const config = configStub();91 const execaStub = sinon.stub().rejects({stderr: 'YA_GOOFED'});92 const useGhostUserStub = sinon.stub().returns(false);93 const migrator = proxyquire(migratePath, {94 execa: execaStub,95 '../utils/use-ghost-user': {shouldUseGhostUser: useGhostUserStub}96 });97 return migrator.migrate({instance: {config, dir: '/some-dir', system: {environment: 'testing'}}}).then(() => {98 expect(false, 'error should have been thrown').to.be.true;99 process.argv = originalArgv;100 }).catch((error) => {101 expect(error).to.be.an.instanceof(errors.ProcessError);102 expect(error.options.stderr).to.match(/YA_GOOFED/);103 expect(error.options.suggestion).to.eql('ghost update --rollback');104 expect(error.options.help).to.exist;105 process.argv = originalArgv;106 });107 });108 it('error on `ghost setup migrate`', function () {109 const originalArgv = process.argv;110 process.argv = ['node', 'ghost', 'setup', 'migrate'];111 const config = configStub();112 const execaStub = sinon.stub().rejects({stderr: 'YA_GOOFED'});113 const useGhostUserStub = sinon.stub().returns(false);114 const migrator = proxyquire(migratePath, {115 execa: execaStub,116 '../utils/use-ghost-user': {shouldUseGhostUser: useGhostUserStub}117 });118 return migrator.migrate({instance: {config, dir: '/some-dir', system: {environment: 'testing'}}}).then(() => {119 expect(false, 'error should have been thrown').to.be.true;120 process.argv = originalArgv;121 }).catch((error) => {122 expect(error).to.be.an.instanceof(errors.ProcessError);123 expect(error.options.stderr).to.match(/YA_GOOFED/);124 expect(error.options.suggestion).to.not.exist;125 expect(error.options.help).to.exist;126 process.argv = originalArgv;127 });128 });129 });130 describe('rollback', function () {131 it('runs direct command if useGhostUser returns false', function () {132 const config = configStub();133 const execaStub = sinon.stub().resolves();134 const useGhostUserStub = sinon.stub().returns(false);135 const migrator = proxyquire(migratePath, {136 execa: execaStub,137 '../utils/use-ghost-user': {shouldUseGhostUser: useGhostUserStub}138 });139 const sudoStub = sinon.stub().resolves();140 return migrator.rollback({instance: {config, version: '1.25.3', dir: '/some-dir'}, ui: {sudo: sudoStub}}).then(() => {141 expect(useGhostUserStub.calledOnce).to.be.true;142 expect(useGhostUserStub.args[0][0]).to.equal('/some-dir/content');143 expect(execaStub.calledOnce).to.be.true;144 expect(execaStub.args[0][0]).to.eql('knex-migrator-rollback');145 expect(execaStub.args[0][1]).to.eql(['--force', '--mgpath', '/some-dir/current']);146 expect(sudoStub.called).to.be.false;147 });148 });149 it('forward version option to knex-migrator if blog jumps from v1 to v2', function () {150 const config = configStub();151 const execaStub = sinon.stub().resolves();152 const useGhostUserStub = sinon.stub().returns(false);153 const migrator = proxyquire(migratePath, {154 execa: execaStub,155 '../utils/use-ghost-user': {shouldUseGhostUser: useGhostUserStub}156 });157 const sudoStub = sinon.stub().resolves();158 return migrator.rollback({instance: {config, version: '2.0.0', previousVersion: '1.25.3', dir: '/some-dir'}, ui: {sudo: sudoStub}}).then(() => {159 expect(useGhostUserStub.calledOnce).to.be.true;160 expect(useGhostUserStub.args[0][0]).to.equal('/some-dir/content');161 expect(execaStub.calledOnce).to.be.true;162 expect(execaStub.args[0][0]).to.eql('knex-migrator-rollback');163 expect(execaStub.args[0][1]).to.eql(['--force', '--v', '1.25.3', '--mgpath', '/some-dir/current']);164 expect(sudoStub.called).to.be.false;165 });166 });167 it('runs sudo command if useGhostUser returns true', function () {168 const config = configStub();169 const execaStub = sinon.stub().resolves();170 const useGhostUserStub = sinon.stub().returns(true);171 const migrator = proxyquire(migratePath, {172 execa: execaStub,173 '../utils/use-ghost-user': {shouldUseGhostUser: useGhostUserStub}174 });175 const sudoStub = sinon.stub().resolves();176 return migrator.rollback({instance: {config, version: '1.25.3', dir: '/some-dir'}, ui: {sudo: sudoStub}}).then(() => {177 expect(useGhostUserStub.calledOnce).to.be.true;178 expect(useGhostUserStub.args[0][0]).to.equal('/some-dir/content');179 expect(execaStub.calledOnce).to.be.false;180 expect(sudoStub.called).to.be.true;181 });182 });183 it('throws config error with db host if database not found', function () {184 const config = configStub();185 const execaStub = sinon.stub().returns(Promise.reject({stderr: 'CODE: ENOTFOUND'}));186 const useGhostUserStub = sinon.stub().returns(false);187 const migrator = proxyquire(migratePath, {188 execa: execaStub,189 '../utils/use-ghost-user': {shouldUseGhostUser: useGhostUserStub}190 });191 return migrator.rollback({instance: {config, version: '1.25.3', dir: '/some-dir', system: {environment: 'testing'}}}).then(() => {192 expect(false, 'error should have been thrown').to.be.true;193 }).catch((error) => {194 expect(error).to.be.an.instanceof(errors.ConfigError);195 expect(error.options.config).to.have.key('database.connection.host');196 });197 });198 it('throws config error with db user if access denied error', function () {199 const config = configStub();200 const execaStub = sinon.stub().returns(Promise.reject({stderr: 'CODE: ER_ACCESS_DENIED_ERROR'}));201 const useGhostUserStub = sinon.stub().returns(false);202 const migrator = proxyquire(migratePath, {203 execa: execaStub,204 '../utils/use-ghost-user': {shouldUseGhostUser: useGhostUserStub}205 });206 return migrator.rollback({instance: {config, version: '1.25.3', dir: '/some-dir', system: {environment: 'testing'}}}).then(() => {207 expect(false, 'error should have been thrown').to.be.true;208 }).catch((error) => {209 expect(error).to.be.an.instanceof(errors.ConfigError);210 expect(error.options.config).to.have.all.keys('database.connection.user', 'database.connection.password');211 });212 });213 it('throws system error if sqlite3 error is thrown by knex', function () {214 const config = configStub();215 const execaStub = sinon.stub().returns(Promise.reject({stdout: 'Knex: run\n$ npm install sqlite3 --save\nError:'}));216 const useGhostUserStub = sinon.stub().returns(false);217 const migrator = proxyquire(migratePath, {218 execa: execaStub,219 '../utils/use-ghost-user': {shouldUseGhostUser: useGhostUserStub}220 });221 return migrator.rollback({instance: {config, version: '1.25.3', dir: '/some-dir', system: {environment: 'testing'}}}).then(() => {222 expect(false, 'error should have been thrown').to.be.true;223 }).catch((error) => {224 expect(error).to.be.an.instanceof(errors.SystemError);225 expect(error.message).to.match(/sqlite3 did not install properly/);226 });227 });228 it('throws ghost error if rollback includes an irreversible migration', function () {229 const config = configStub();230 const execaStub = sinon.stub().returns(Promise.reject({stdout: 'There are irreversible migrations when rolling back to the selected version, this typically means data required for earlier versions has been deleted. Please restore from a backup instead.'}));231 const useGhostUserStub = sinon.stub().returns(false);232 const migrator = proxyquire(migratePath, {233 execa: execaStub,234 '../utils/use-ghost-user': {shouldUseGhostUser: useGhostUserStub}235 });236 return migrator.rollback({237 activeVersion: '3.0.0',238 version: '2.36.0',239 instance: {config, version: '3.0.0', previousVersion: '2.36.0', dir: '/some-dir', system: {environment: 'testing'}}240 }).then(() => {241 expect(false, 'error should have been thrown').to.be.true;242 }).catch((error) => {243 expect(error).to.be.an.instanceof(errors.ProcessError);244 expect(error.message).to.match(/not possible to roll back database changes from 3.0.0 to 2.36.0/);245 });246 });247 it('knex-migrator complains that no more migrations to rollback available', function () {248 const config = configStub();249 const execaStub = sinon.stub().returns(Promise.reject({stderr: 'No migrations available to rollback'}));250 const useGhostUserStub = sinon.stub().returns(false);251 const migrator = proxyquire(migratePath, {252 execa: execaStub,253 '../utils/use-ghost-user': {shouldUseGhostUser: useGhostUserStub}254 });255 return migrator.rollback({instance: {config, version: '1.25.3', dir: '/some-dir', system: {environment: 'testing'}}});256 });257 it('error on `ghost update --rollback`', function () {258 const originalArgv = process.argv;259 process.argv = ['node', 'ghost', 'update', '--rollback'];260 const config = configStub();261 const execaStub = sinon.stub().rejects({stderr: 'YA_GOOFED'});262 const useGhostUserStub = sinon.stub().returns(false);263 const migrator = proxyquire(migratePath, {264 execa: execaStub,265 '../utils/use-ghost-user': {shouldUseGhostUser: useGhostUserStub}266 });267 return migrator.rollback({instance: {config, version: '1.25.3', dir: '/some-dir', system: {environment: 'testing'}}}).then(() => {268 expect(false, 'error should have been thrown').to.be.true;269 process.argv = originalArgv;270 }).catch((error) => {271 expect(error).to.be.an.instanceof(errors.ProcessError);272 expect(error.options.stderr).to.match(/YA_GOOFED/);273 expect(error.options.suggestion).to.eql('ghost update --rollback');274 expect(error.options.help).to.exist;275 process.argv = originalArgv;276 });277 });278 });...
git-utils.js
Source:git-utils.js
...22 * @return {String} The path of the repository23 */24async function initGit(withRemote) {25 const cwd = tempy.directory();26 await execa('git', ['init', ...(withRemote ? ['--bare'] : [])], {cwd});27 const repositoryUrl = fileUrl(cwd);28 return {cwd, repositoryUrl};29}30/**31 * Create a temporary git repository.32 * If `withRemote` is `true`, creates a shallow clone. Change the current working directory to the clone root.33 * If `withRemote` is `false`, just change the current working directory to the repository root.34 *35 *36 * @param {Boolean} withRemote `true` to create a shallow clone of a bare repository.37 * @param {String} [branch='master'] The branch to initialize.38 * @return {String} The path of the clone if `withRemote` is `true`, the path of the repository otherwise.39 */40async function gitRepo(withRemote, branch = 'master') {41 let {cwd, repositoryUrl} = await initGit(withRemote);42 if (withRemote) {43 await initBareRepo(repositoryUrl, branch);44 cwd = await gitShallowClone(repositoryUrl, branch);45 } else {46 await gitCheckout(branch, true, {cwd});47 }48 await execa('git', ['config', 'commit.gpgsign', false], {cwd});49 return {cwd, repositoryUrl};50}51/**52 * Initialize an existing bare repository:53 * - Clone the repository54 * - Change the current working directory to the clone root55 * - Create a default branch56 * - Create an initial commits57 * - Push to origin58 *59 * @param {String} repositoryUrl The URL of the bare repository.60 * @param {String} [branch='master'] the branch to initialize.61 */62async function initBareRepo(repositoryUrl, branch = 'master') {63 const cwd = tempy.directory();64 await execa('git', ['clone', '--no-hardlinks', repositoryUrl, cwd], {cwd});65 await gitCheckout(branch, true, {cwd});66 await gitCommits(['Initial commit'], {cwd});67 await execa('git', ['push', repositoryUrl, branch], {cwd});68}69/**70 * Create commits on the current git repository.71 *72 * @param {Array<string>} messages Commit messages.73 * @param {Object} [execaOpts] Options to pass to `execa`.74 *75 * @returns {Array<Commit>} The created commits, in reverse order (to match `git log` order).76 */77async function gitCommits(messages, execaOptions) {78 await pEachSeries(79 messages,80 async (message) =>81 (await execa('git', ['commit', '-m', message, '--allow-empty', '--no-gpg-sign'], execaOptions)).stdout82 );83 return (await gitGetCommits(undefined, execaOptions)).slice(0, messages.length);84}85/**86 * Get the list of parsed commits since a git reference.87 *88 * @param {String} [from] Git reference from which to seach commits.89 * @param {Object} [execaOpts] Options to pass to `execa`.90 *91 * @return {Array<Object>} The list of parsed commits.92 */93async function gitGetCommits(from, execaOptions) {94 Object.assign(gitLogParser.fields, {hash: 'H', message: 'B', gitTags: 'd', committerDate: {key: 'ci', type: Date}});95 return (96 await getStream.array(97 gitLogParser.parse(98 {_: `${from ? from + '..' : ''}HEAD`},99 {...execaOptions, env: {...process.env, ...execaOptions.env}}100 )101 )102 ).map((commit) => {103 commit.message = commit.message.trim();104 commit.gitTags = commit.gitTags.trim();105 return commit;106 });107}108/**109 * Checkout a branch on the current git repository.110 *111 * @param {String} branch Branch name.112 * @param {Boolean} create to create the branch, `false` to checkout an existing branch.113 * @param {Object} [execaOpts] Options to pass to `execa`.114 */115async function gitCheckout(branch, create, execaOptions) {116 await execa('git', create ? ['checkout', '-b', branch] : ['checkout', branch], execaOptions);117}118/**119 * Fetch current git repository.120 *121 * @param {String} repositoryUrl The repository remote URL.122 * @param {Object} [execaOpts] Options to pass to `execa`.123 */124async function gitFetch(repositoryUrl, execaOptions) {125 await execa('git', ['fetch', repositoryUrl], execaOptions);126}127/**128 * Get the HEAD sha.129 *130 * @param {Object} [execaOpts] Options to pass to `execa`.131 *132 * @return {String} The sha of the head commit in the current git repository.133 */134async function gitHead(execaOptions) {135 return (await execa('git', ['rev-parse', 'HEAD'], execaOptions)).stdout;136}137/**138 * Create a tag on the head commit in the current git repository.139 *140 * @param {String} tagName The tag name to create.141 * @param {String} [sha] The commit on which to create the tag. If undefined the tag is created on the last commit.142 * @param {Object} [execaOpts] Options to pass to `execa`.143 */144async function gitTagVersion(tagName, sha, execaOptions) {145 await execa('git', sha ? ['tag', '-f', tagName, sha] : ['tag', tagName], execaOptions);146}147/**148 * Create a shallow clone of a git repository and change the current working directory to the cloned repository root.149 * The shallow will contain a limited number of commit and no tags.150 *151 * @param {String} repositoryUrl The path of the repository to clone.152 * @param {String} [branch='master'] the branch to clone.153 * @param {Number} [depth=1] The number of commit to clone.154 * @return {String} The path of the cloned repository.155 */156async function gitShallowClone(repositoryUrl, branch = 'master', depth = 1) {157 const cwd = tempy.directory();158 await execa('git', ['clone', '--no-hardlinks', '--no-tags', '-b', branch, '--depth', depth, repositoryUrl, cwd], {159 cwd,160 });161 return cwd;162}163/**164 * Create a git repo with a detached head from another git repository and change the current working directory to the new repository root.165 *166 * @param {String} repositoryUrl The path of the repository to clone.167 * @param {Number} head A commit sha of the remote repo that will become the detached head of the new one.168 * @return {String} The path of the new repository.169 */170async function gitDetachedHead(repositoryUrl, head) {171 const cwd = tempy.directory();172 await execa('git', ['init'], {cwd});173 await execa('git', ['remote', 'add', 'origin', repositoryUrl], {cwd});174 await execa('git', ['fetch', repositoryUrl], {cwd});175 await execa('git', ['checkout', head], {cwd});176 return cwd;177}178async function gitDetachedHeadFromBranch(repositoryUrl, branch, head) {179 const cwd = tempy.directory();180 await execa('git', ['init'], {cwd});181 await execa('git', ['remote', 'add', 'origin', repositoryUrl], {cwd});182 await execa('git', ['fetch', '--force', repositoryUrl, `${branch}:remotes/origin/${branch}`], {cwd});183 await execa('git', ['reset', '--hard', head], {cwd});184 await execa('git', ['checkout', '-q', '-B', branch], {cwd});185 return cwd;186}187/**188 * Add a new Git configuration.189 *190 * @param {String} name Config name.191 * @param {String} value Config value.192 * @param {Object} [execaOpts] Options to pass to `execa`.193 */194async function gitAddConfig(name, value, execaOptions) {195 await execa('git', ['config', '--add', name, value], execaOptions);196}197/**198 * Get the first commit sha referenced by the tag `tagName` in the local repository.199 *200 * @param {String} tagName Tag name for which to retrieve the commit sha.201 * @param {Object} [execaOpts] Options to pass to `execa`.202 *203 * @return {String} The sha of the commit associated with `tagName` on the local repository.204 */205async function gitTagHead(tagName, execaOptions) {206 return (await execa('git', ['rev-list', '-1', tagName], execaOptions)).stdout;207}208/**209 * Get the first commit sha referenced by the tag `tagName` in the remote repository.210 *211 * @param {String} repositoryUrl The repository remote URL.212 * @param {String} tagName The tag name to seach for.213 * @param {Object} [execaOpts] Options to pass to `execa`.214 *215 * @return {String} The sha of the commit associated with `tagName` on the remote repository.216 */217async function gitRemoteTagHead(repositoryUrl, tagName, execaOptions) {218 return (await execa('git', ['ls-remote', '--tags', repositoryUrl, tagName], execaOptions)).stdout219 .split('\n')220 .filter((tag) => Boolean(tag))221 .map((tag) => tag.match(/^(?<tag>\S+)/)[1])[0];222}223/**224 * Get the tag associated with a commit sha.225 *226 * @param {String} gitHead The commit sha for which to retrieve the associated tag.227 * @param {Object} [execaOpts] Options to pass to `execa`.228 *229 * @return {String} The tag associatedwith the sha in parameter or `null`.230 */231async function gitCommitTag(gitHead, execaOptions) {232 return (await execa('git', ['describe', '--tags', '--exact-match', gitHead], execaOptions)).stdout;233}234/**235 * Push to the remote repository.236 *237 * @param {String} repositoryUrl The remote repository URL.238 * @param {String} branch The branch to push.239 * @param {Object} [execaOpts] Options to pass to `execa`.240 *241 * @throws {Error} if the push failed.242 */243async function gitPush(repositoryUrl, branch, execaOptions) {244 await execa('git', ['push', '--tags', repositoryUrl, `HEAD:${branch}`], execaOptions);245}246/**247 * Merge a branch into the current one with `git merge`.248 *249 * @param {String} ref The ref to merge.250 * @param {Object} [execaOpts] Options to pass to `execa`.251 */252async function merge(ref, execaOptions) {253 await execa('git', ['merge', '--no-ff', ref], execaOptions);254}255/**256 * Merge a branch into the current one with `git merge --ff`.257 *258 * @param {String} ref The ref to merge.259 * @param {Object} [execaOpts] Options to pass to `execa`.260 */261async function mergeFf(ref, execaOptions) {262 await execa('git', ['merge', '--ff', ref], execaOptions);263}264/**265 * Merge a branch into the current one with `git rebase`.266 *267 * @param {String} ref The ref to merge.268 * @param {Object} [execaOpts] Options to pass to `execa`.269 */270async function rebase(ref, execaOptions) {271 await execa('git', ['rebase', ref], execaOptions);272}273/**274 * Add a note to a Git reference.275 *276 * @param {String} note The note to add.277 * @param {String} ref The ref to add the note to.278 * @param {Object} [execaOpts] Options to pass to `execa`.279 */280async function gitAddNote(note, ref, execaOptions) {281 await execa('git', ['notes', '--ref', GIT_NOTE_REF, 'add', '-m', note, ref], execaOptions);282}283/**284 * Get the note associated with a Git reference.285 *286 * @param {String} ref The ref to get the note from.287 * @param {Object} [execaOpts] Options to pass to `execa`.288 */289async function gitGetNote(ref, execaOptions) {290 return (await execa('git', ['notes', '--ref', GIT_NOTE_REF, 'show', ref], execaOptions)).stdout;291}292module.exports = {293 initGit,294 gitRepo,295 initBareRepo,296 gitCommits,297 gitGetCommits,298 gitCheckout,299 gitFetch,300 gitHead,301 gitTagVersion,302 gitShallowClone,303 gitDetachedHead,304 gitDetachedHeadFromBranch,...
git.js
Source:git.js
...12 *13 * @return {String} The commit sha of the tag in parameter or `null`.14 */15async function getTagHead(tagName, execaOptions) {16 return (await execa('git', ['rev-list', '-1', tagName], execaOptions)).stdout;17}18/**19 * Get all the tags for a given branch.20 *21 * @param {String} branch The branch for which to retrieve the tags.22 * @param {Object} [execaOpts] Options to pass to `execa`.23 *24 * @return {Array<String>} List of git tags.25 * @throws {Error} If the `git` command fails.26 */27async function getTags(branch, execaOptions) {28 return (await execa('git', ['tag', '--merged', branch], execaOptions)).stdout29 .split('\n')30 .map((tag) => tag.trim())31 .filter(Boolean);32}33/**34 * Retrieve a range of commits.35 *36 * @param {String} from to includes all commits made after this sha (does not include this sha).37 * @param {String} to to includes all commits made before this sha (also include this sha).38 * @param {Object} [execaOpts] Options to pass to `execa`.39 * @return {Promise<Array<Object>>} The list of commits between `from` and `to`.40 */41async function getCommits(from, to, execaOptions) {42 return (43 await getStream.array(44 gitLogParser.parse(45 {_: `${from ? from + '..' : ''}${to}`},46 {cwd: execaOptions.cwd, env: {...process.env, ...execaOptions.env}}47 )48 )49 ).map(({message, gitTags, ...commit}) => ({...commit, message: message.trim(), gitTags: gitTags.trim()}));50}51/**52 * Get all the repository branches.53 *54 * @param {String} repositoryUrl The remote repository URL.55 * @param {Object} [execaOpts] Options to pass to `execa`.56 *57 * @return {Array<String>} List of git branches.58 * @throws {Error} If the `git` command fails.59 */60async function getBranches(repositoryUrl, execaOptions) {61 return (await execa('git', ['ls-remote', '--heads', repositoryUrl], execaOptions)).stdout62 .split('\n')63 .filter(Boolean)64 .map((branch) => branch.match(/^.+refs\/heads\/(?<branch>.+)$/)[1]);65}66/**67 * Verify if the `ref` exits68 *69 * @param {String} ref The reference to verify.70 * @param {Object} [execaOpts] Options to pass to `execa`.71 *72 * @return {Boolean} `true` if the reference exists, falsy otherwise.73 */74async function isRefExists(ref, execaOptions) {75 try {76 return (await execa('git', ['rev-parse', '--verify', ref], execaOptions)).exitCode === 0;77 } catch (error) {78 debug(error);79 }80}81/**82 * Fetch all the tags from a branch. Unshallow if necessary.83 * This will update the local branch from the latest on the remote if:84 * - The branch is not the one that triggered the CI85 * - The CI created a detached head86 *87 * Otherwise it just calls `git fetch` without specifying the `refspec` option to avoid overwritting the head commit set by the CI.88 *89 * The goal is to retrieve the informations on all the release branches without "disturbing" the CI, leaving the trigger branch or the detached head intact.90 *91 * @param {String} repositoryUrl The remote repository URL.92 * @param {String} branch The repository branch to fetch.93 * @param {Object} [execaOpts] Options to pass to `execa`.94 */95async function fetch(repositoryUrl, branch, ciBranch, execaOptions) {96 const isDetachedHead =97 (await execa('git', ['rev-parse', '--abbrev-ref', 'HEAD'], {...execaOptions, reject: false})).stdout === 'HEAD';98 try {99 await execa(100 'git',101 [102 'fetch',103 '--unshallow',104 '--tags',105 ...(branch === ciBranch && !isDetachedHead106 ? [repositoryUrl]107 : ['--update-head-ok', repositoryUrl, `+refs/heads/${branch}:refs/heads/${branch}`]),108 ],109 execaOptions110 );111 } catch (_) {112 await execa(113 'git',114 [115 'fetch',116 '--tags',117 ...(branch === ciBranch && !isDetachedHead118 ? [repositoryUrl]119 : ['--update-head-ok', repositoryUrl, `+refs/heads/${branch}:refs/heads/${branch}`]),120 ],121 execaOptions122 );123 }124}125/**126 * Unshallow the git repository if necessary and fetch all the notes.127 *128 * @param {String} repositoryUrl The remote repository URL.129 * @param {Object} [execaOpts] Options to pass to `execa`.130 */131async function fetchNotes(repositoryUrl, execaOptions) {132 try {133 await execa(134 'git',135 ['fetch', '--unshallow', repositoryUrl, `+refs/notes/${GIT_NOTE_REF}:refs/notes/${GIT_NOTE_REF}`],136 execaOptions137 );138 } catch (_) {139 await execa('git', ['fetch', repositoryUrl, `+refs/notes/${GIT_NOTE_REF}:refs/notes/${GIT_NOTE_REF}`], {140 ...execaOptions,141 reject: false,142 });143 }144}145/**146 * Get the HEAD sha.147 *148 * @param {Object} [execaOpts] Options to pass to `execa`.149 *150 * @return {String} the sha of the HEAD commit.151 */152async function getGitHead(execaOptions) {153 return (await execa('git', ['rev-parse', 'HEAD'], execaOptions)).stdout;154}155/**156 * Get the repository remote URL.157 *158 * @param {Object} [execaOpts] Options to pass to `execa`.159 *160 * @return {string} The value of the remote git URL.161 */162async function repoUrl(execaOptions) {163 try {164 return (await execa('git', ['config', '--get', 'remote.origin.url'], execaOptions)).stdout;165 } catch (error) {166 debug(error);167 }168}169/**170 * Test if the current working directory is a Git repository.171 *172 * @param {Object} [execaOpts] Options to pass to `execa`.173 *174 * @return {Boolean} `true` if the current working directory is in a git repository, falsy otherwise.175 */176async function isGitRepo(execaOptions) {177 try {178 return (await execa('git', ['rev-parse', '--git-dir'], execaOptions)).exitCode === 0;179 } catch (error) {180 debug(error);181 }182}183/**184 * Verify the write access authorization to remote repository with push dry-run.185 *186 * @param {String} repositoryUrl The remote repository URL.187 * @param {String} branch The repository branch for which to verify write access.188 * @param {Object} [execaOpts] Options to pass to `execa`.189 *190 * @throws {Error} if not authorized to push.191 */192async function verifyAuth(repositoryUrl, branch, execaOptions) {193 try {194 await execa('git', ['push', '--dry-run', '--no-verify', repositoryUrl, `HEAD:${branch}`], execaOptions);195 } catch (error) {196 debug(error);197 throw error;198 }199}200/**201 * Tag the commit head on the local repository.202 *203 * @param {String} tagName The name of the tag.204 * @param {String} ref The Git reference to tag.205 * @param {Object} [execaOpts] Options to pass to `execa`.206 *207 * @throws {Error} if the tag creation failed.208 */209async function tag(tagName, ref, execaOptions) {210 await execa('git', ['tag', tagName, ref], execaOptions);211}212/**213 * Push to the remote repository.214 *215 * @param {String} repositoryUrl The remote repository URL.216 * @param {Object} [execaOpts] Options to pass to `execa`.217 *218 * @throws {Error} if the push failed.219 */220async function push(repositoryUrl, execaOptions) {221 await execa('git', ['push', '--tags', repositoryUrl], execaOptions);222}223/**224 * Push notes to the remote repository.225 *226 * @param {String} repositoryUrl The remote repository URL.227 * @param {Object} [execaOpts] Options to pass to `execa`.228 *229 * @throws {Error} if the push failed.230 */231async function pushNotes(repositoryUrl, execaOptions) {232 await execa('git', ['push', repositoryUrl, `refs/notes/${GIT_NOTE_REF}`], execaOptions);233}234/**235 * Verify a tag name is a valid Git reference.236 *237 * @param {String} tagName the tag name to verify.238 * @param {Object} [execaOpts] Options to pass to `execa`.239 *240 * @return {Boolean} `true` if valid, falsy otherwise.241 */242async function verifyTagName(tagName, execaOptions) {243 try {244 return (await execa('git', ['check-ref-format', `refs/tags/${tagName}`], execaOptions)).exitCode === 0;245 } catch (error) {246 debug(error);247 }248}249/**250 * Verify a branch name is a valid Git reference.251 *252 * @param {String} branch the branch name to verify.253 * @param {Object} [execaOpts] Options to pass to `execa`.254 *255 * @return {Boolean} `true` if valid, falsy otherwise.256 */257async function verifyBranchName(branch, execaOptions) {258 try {259 return (await execa('git', ['check-ref-format', `refs/heads/${branch}`], execaOptions)).exitCode === 0;260 } catch (error) {261 debug(error);262 }263}264/**265 * Verify the local branch is up to date with the remote one.266 *267 * @param {String} repositoryUrl The remote repository URL.268 * @param {String} branch The repository branch for which to verify status.269 * @param {Object} [execaOpts] Options to pass to `execa`.270 *271 * @return {Boolean} `true` is the HEAD of the current local branch is the same as the HEAD of the remote branch, falsy otherwise.272 */273async function isBranchUpToDate(repositoryUrl, branch, execaOptions) {274 return (275 (await getGitHead(execaOptions)) ===276 (await execa('git', ['ls-remote', '--heads', repositoryUrl, branch], execaOptions)).stdout.match(/^(?<ref>\w+)?/)[1]277 );278}279/**280 * Get and parse the JSON note of a given reference.281 *282 * @param {String} ref The Git reference for which to retrieve the note.283 * @param {Object} [execaOpts] Options to pass to `execa`.284 *285 * @return {Object} the parsed JSON note if there is one, an empty object otherwise.286 */287async function getNote(ref, execaOptions) {288 try {289 return JSON.parse((await execa('git', ['notes', '--ref', GIT_NOTE_REF, 'show', ref], execaOptions)).stdout);290 } catch (error) {291 if (error.exitCode === 1) {292 return {};293 }294 debug(error);295 throw error;296 }297}298/**299 * Get and parse the JSON note of a given reference.300 *301 * @param {Object} note The object to save in the reference note.302 * @param {String} ref The Git reference to add the note to.303 * @param {Object} [execaOpts] Options to pass to `execa`.304 */305async function addNote(note, ref, execaOptions) {306 await execa('git', ['notes', '--ref', GIT_NOTE_REF, 'add', '-f', '-m', JSON.stringify(note), ref], execaOptions);307}308module.exports = {309 getTagHead,310 getTags,311 getCommits,312 getBranches,313 isRefExists,314 fetch,315 fetchNotes,316 getGitHead,317 repoUrl,318 isGitRepo,319 verifyAuth,320 tag,...
yarn-spec.js
Source:yarn-spec.js
1'use strict';2const expect = require('chai').expect;3const proxyquire = require('proxyquire');4const sinon = require('sinon');5const {isObservable} = require('rxjs');6const {getReadableStream} = require('../../utils/stream');7const {ProcessError} = require('../../../lib/errors');8const modulePath = '../../../lib/utils/yarn';9const setup = proxies => proxyquire(modulePath, proxies);10describe('Unit: yarn', function () {11 let currentEnv;12 beforeEach(function () {13 currentEnv = process.env;14 process.env = {};15 });16 afterEach(function () {17 process.env = currentEnv;18 });19 it('spawns yarn process with no arguments correctly', function () {20 const execa = sinon.stub().resolves();21 const yarn = setup({execa});22 return yarn().then(function () {23 expect(execa.calledOnce).to.be.true;24 expect(execa.args[0]).to.be.ok;25 expect(execa.args[0]).to.have.lengthOf(3);26 expect(execa.args[0][1]).to.deep.equal([]);27 });28 });29 it('spawns yarn process with correct arguments', function () {30 const execa = sinon.stub().resolves();31 const yarn = setup({execa});32 return yarn(['cache', 'clear']).then(function () {33 expect(execa.calledOnce).to.be.true;34 expect(execa.args[0]).to.be.ok;35 expect(execa.args[0]).to.have.lengthOf(3);36 expect(execa.args[0][1]).to.deep.equal(['cache', 'clear']);37 });38 });39 it('adds verbose option correctly', function () {40 const execa = sinon.stub().resolves();41 const yarn = setup({execa});42 return yarn(['cache', 'clear'], {verbose: true}).then(function () {43 expect(execa.calledOnce).to.be.true;44 expect(execa.args[0]).to.be.ok;45 expect(execa.args[0]).to.have.lengthOf(3);46 expect(execa.args[0][1]).to.deep.equal(['cache', 'clear', '--verbose']);47 });48 });49 it('correctly passes through options', function () {50 const execa = sinon.stub().resolves();51 const yarn = setup({execa});52 return yarn([], {cwd: 'test'}).then(function () {53 expect(execa.calledOnce).to.be.true;54 expect(execa.args[0]).to.be.ok;55 expect(execa.args[0]).to.have.lengthOf(3);56 expect(execa.args[0][2]).to.be.an('object');57 expect(execa.args[0][2].cwd).to.equal('test');58 });59 });60 it('respects process.env overrides but doesn\'t mutate process.env', function () {61 const execa = sinon.stub().resolves();62 const yarn = setup({execa});63 process.env.TESTENV = 'test';64 return yarn([], {env: {TESTENV: 'override'}}).then(() => {65 expect(execa.calledOnce).to.be.true;66 expect(execa.args[0][2]).to.be.an('object');67 expect(execa.args[0][2].env).to.be.an('object');68 expect(execa.args[0][2].env.TESTENV).to.equal('override');69 expect(process.env.TESTENV).to.equal('test');70 });71 });72 it('fails gracefully when yarn fails', function () {73 const execa = sinon.stub().rejects(new Error('YARN_TO_FAST'));74 const yarn = setup({execa});75 return yarn().then(() => {76 expect(false, 'Promise should have rejected').to.be.true;77 }).catch((error) => {78 expect(execa.calledOnce).to.be.true;79 expect(error).to.be.ok;80 expect(error).to.be.instanceOf(ProcessError);81 });82 });83 describe('can return observables', function () {84 it('ends properly', function () {85 const execa = sinon.stub().callsFake(() => {86 const promise = Promise.resolve();87 promise.stdout = getReadableStream();88 return promise;89 });90 const yarn = setup({execa});91 const res = yarn([], {observe: true});92 expect(isObservable(res)).to.be.true;93 const subscriber = {94 next: sinon.stub(),95 error: sinon.stub(),96 complete: sinon.stub()97 };98 res.subscribe(subscriber);99 return res.toPromise().then(() => {100 expect(execa.calledOnce).to.be.true;101 expect(subscriber.next.called).to.be.false;102 expect(subscriber.error.called).to.be.false;103 expect(subscriber.complete.calledOnce).to.be.true;104 });105 });106 it('ends properly (error)', function () {107 const execa = sinon.stub().callsFake(() => {108 const promise = Promise.reject(new Error('test error'));109 promise.stdout = getReadableStream();110 return promise;111 });112 const yarn = setup({execa});113 const res = yarn([], {observe: true});114 expect(isObservable(res)).to.be.true;115 const subscriber = {116 next: sinon.stub(),117 error: sinon.stub(),118 complete: sinon.stub()119 };120 res.subscribe(subscriber);121 return res.toPromise().catch((error) => {122 expect(error.message).to.equal('test error');123 expect(execa.calledOnce).to.be.true;124 expect(subscriber.next.called).to.be.false;125 expect(subscriber.error.calledOnce).to.be.true;126 expect(subscriber.error.args[0][0]).to.be.an.instanceOf(ProcessError);127 expect(subscriber.complete.called).to.be.false;128 });129 });130 it('passes data through', function () {131 const execa = sinon.stub().callsFake(() => {132 const promise = Promise.resolve();133 promise.stdout = getReadableStream(function () {134 this.push('test message\n');135 this.push(null);136 });137 return promise;138 });139 const yarn = setup({execa});140 const res = yarn([], {observe: true});141 expect(isObservable(res)).to.be.true;142 const subscriber = {143 next: sinon.stub(),144 error: sinon.stub(),145 complete: sinon.stub()146 };147 res.subscribe(subscriber);148 return res.toPromise().then(() => {149 expect(execa.calledOnce).to.be.true;150 expect(subscriber.next.calledOnce).to.be.true;151 expect(subscriber.next.calledWithExactly('test message')).to.be.true;152 expect(subscriber.error.called).to.be.false;153 expect(subscriber.complete.calledOnce).to.be.true;154 });155 });156 it('passes data through with verbose', function () {157 const execa = sinon.stub().callsFake(() => {158 const promise = Promise.resolve();159 promise.stdout = getReadableStream(function () {160 this.push('test message\n');161 this.push(null);162 });163 promise.stderr = getReadableStream(function () {164 this.push('test stderr message\n');165 this.push(null);166 });167 return promise;168 });169 const yarn = setup({execa});170 const res = yarn([], {observe: true, verbose: true});171 expect(isObservable(res)).to.be.true;172 const subscriber = {173 next: sinon.stub(),174 error: sinon.stub(),175 complete: sinon.stub()176 };177 res.subscribe(subscriber);178 return res.toPromise().then(() => {179 expect(execa.calledOnce).to.be.true;180 expect(subscriber.next.calledTwice).to.be.true;181 expect(subscriber.next.calledWithExactly('test message')).to.be.true;182 expect(subscriber.next.calledWithExactly('test stderr message')).to.be.true;183 expect(subscriber.error.called).to.be.false;184 expect(subscriber.complete.calledOnce).to.be.true;185 });186 });187 });...
generators-integration.test.js
Source:generators-integration.test.js
...9describe('without a linter', () => {10 beforeAll(async () => {11 // creates a new temp directory12 process.chdir(tempy.directory())13 await execa(IGNITE, ['new', APP, '--min', '--skip-git', '--no-lint', '--boilerplate', BOILERPLATE])14 process.chdir(APP)15 })16 test('does not have a linting script', async () => {17 expect(jetpack.read('package.json', 'json')['scripts']['lint']).toBe(undefined)18 })19})20describe('generators', () => {21 beforeAll(async () => {22 // creates a new temp directory23 process.chdir(tempy.directory())24 await execa(IGNITE, ['new', APP, '--min', '--skip-git', '--boilerplate', BOILERPLATE])25 process.chdir(APP)26 })27 test('generates a component', async () => {28 const simpleComponent = 'Simple'29 await execa(IGNITE, ['g', 'component', simpleComponent], { preferLocal: false })30 expect(jetpack.exists(`App/Components/${simpleComponent}.js`)).toBe('file')31 expect(jetpack.exists(`App/Components/Styles/${simpleComponent}Style.js`)).toBe('file')32 const lint = await execa('npm', ['-s', 'run', 'lint'])33 expect(lint.stderr).toBe('')34 })35 test('generates a folder component', async () => {36 const folderComponent = 'Folder'37 await execa(IGNITE, ['g', 'component', '--folder', folderComponent], { preferLocal: false })38 expect(jetpack.exists(`App/Components/${folderComponent}/index.js`)).toBe('file')39 expect(jetpack.exists(`App/Components/${folderComponent}/Styles/indexStyle.js`)).toBe('file')40 const lint = await execa('npm', ['-s', 'run', 'lint'])41 expect(lint.stderr).toBe('')42 })43 test('generates a component inside a folder', async () => {44 const componentName = 'InFolder'45 const folderName = 'Folder'46 await execa(IGNITE, ['g', 'component', '--folder', folderName, componentName], { preferLocal: false })47 expect(jetpack.exists(`App/Components/${folderName}/${componentName}.js`)).toBe('file')48 expect(jetpack.exists(`App/Components/${folderName}/Styles/${componentName}Style.js`)).toBe('file')49 const lint = await execa('npm', ['-s', 'run', 'lint'])50 expect(lint.stderr).toBe('')51 })52 test('generates a component in a relative path', async() => {53 await execa(IGNITE, ['g', 'component', 'My/SubFolder/Test'], { preferLocal: false })54 expect(jetpack.exists('App/Components/My/SubFolder/Test.js')).toBe('file')55 expect(jetpack.exists('App/Components/My/SubFolder/Styles/TestStyle.js')).toBe('file')56 const lint = await execa('npm', ['-s', 'run', 'lint'])57 expect(lint.stderr).toBe('')58 })59 test('generate listview of type row works', async () => {60 await execa(IGNITE, ['g', 'list', 'TestRow', '--type=Row', '--codeType=listview', '--dataType=Single'], { preferLocal: false })61 expect(jetpack.exists('App/Containers/TestRow.js')).toBe('file')62 expect(jetpack.exists('App/Containers/Styles/TestRowStyle.js')).toBe('file')63 const lint = await execa('npm', ['run', 'lint'])64 expect(lint.stderr).toBe('')65 })66 test('generate flatlist of type row works', async () => {67 await execa(IGNITE, ['g', 'list', 'TestFlatRow', '--type=Row', '--codeType=flatlist', '--dataType=Single'], { preferLocal: false })68 expect(jetpack.exists('App/Containers/TestFlatRow.js')).toBe('file')69 expect(jetpack.exists('App/Containers/Styles/TestFlatRowStyle.js')).toBe('file')70 const lint = await execa('npm', ['run', 'lint'])71 expect(lint.stderr).toBe('')72 })73 test('generate listview of sections works', async () => {74 await execa(IGNITE, ['g', 'list', 'TestSection', '--type=Row', '--codeType=listview', '--dataType=Sectioned'], { preferLocal: false })75 expect(jetpack.exists('App/Containers/TestSection.js')).toBe('file')76 expect(jetpack.exists('App/Containers/Styles/TestSectionStyle.js')).toBe('file')77 const lint = await execa('npm', ['run', 'lint'])78 expect(lint.stderr).toBe('')79 })80 test('generate flatlist of sections works', async () => {81 await execa(IGNITE, ['g', 'list', 'TestFlatSection', '--type=Row', '--codeType=flatlist', '--dataType=Sectioned'], { preferLocal: false })82 expect(jetpack.exists('App/Containers/TestFlatSection.js')).toBe('file')83 expect(jetpack.exists('App/Containers/Styles/TestFlatSectionStyle.js')).toBe('file')84 const lint = await execa('npm', ['run', 'lint'])85 expect(lint.stderr).toBe('')86 })87 test('generate listview of type grid works', async () => {88 await execa(IGNITE, ['g', 'list', 'TestGrid', '--type=Grid', '--codeType=listview', '--dataType=Single'], { preferLocal: false })89 expect(jetpack.exists('App/Containers/TestGrid.js')).toBe('file')90 expect(jetpack.exists('App/Containers/Styles/TestGridStyle.js')).toBe('file')91 const lint = await execa('npm', ['run', 'lint'])92 expect(lint.stderr).toBe('')93 })94 test('generate redux works', async () => {95 await execa(IGNITE, ['g', 'redux', 'Test'], { preferLocal: false })96 expect(jetpack.exists('App/Redux/TestRedux.js')).toBe('file')97 const lint = await execa('npm', ['run', 'lint'])98 expect(lint.stderr).toBe('')99 })100 test('generate container works', async () => {101 await execa(IGNITE, ['g', 'container', 'Container'], { preferLocal: false })102 expect(jetpack.exists('App/Containers/Container.js')).toBe('file')103 expect(jetpack.exists('App/Containers/Styles/ContainerStyle.js')).toBe('file')104 const lint = await execa('npm', ['run', 'lint'])105 expect(lint.stderr).toBe('')106 })107 test('generate saga works', async () => {108 await execa(IGNITE, ['g', 'saga', 'Test'], { preferLocal: false })109 expect(jetpack.exists('App/Sagas/TestSagas.js')).toBe('file')110 const lint = await execa('npm', ['run', 'lint'])111 expect(lint.stderr).toBe('')112 })113 test('generate screen works', async () => {114 await execa(IGNITE, ['g', 'screen', 'Test'], { preferLocal: false })115 expect(jetpack.exists('App/Containers/TestScreen.js')).toBe('file')116 expect(jetpack.exists('App/Containers/Styles/TestScreenStyle.js')).toBe('file')117 const lint = await execa('npm', ['run', 'lint'])118 expect(lint.stderr).toBe('')119 })...
build.js
Source:build.js
2const path = require('path')3const test = require('ava')4const execa = require('execa')5test('builds an object with the correct shape', t => {6 return execa(7 path.resolve(__dirname, '../script/build.js'),8 ['--input', 'icons/icon-a-16.svg', './icons/icon-a-24.svg', './icons/icon-b-16.svg'],9 {cwd: __dirname}10 ).then(({stdout}) => {11 const icons = JSON.parse(stdout)12 t.snapshot(icons)13 })14})15test('fails when input argument is missing', t => {16 return execa(path.resolve(__dirname, '../script/build.js'))17 .then(() => {18 t.fail() // Test should fail if execa() call doesn't throw an error19 })20 .catch(error => {21 t.is(error.exitCode, 1)22 t.false(error.killed)23 })24})25test('fails when input file does not exist', t => {26 return execa(path.resolve(__dirname, '../script/build.js'), ['--input', 'fake-16.svg'])27 .then(() => {28 t.fail() // Test should fail if execa() call doesn't throw an error29 })30 .catch(error => {31 t.is(error.exitCode, 1)32 t.false(error.killed)33 })34})35test('fails when filename is missing a height', t => {36 return execa(path.resolve(__dirname, '../script/build.js'), ['--input', 'tests/icons/missing-height.svg'])37 .then(() => {38 t.fail() // Test should fail if execa() call doesn't throw an error39 })40 .catch(error => {41 t.is(error.exitCode, 1)42 t.false(error.killed)43 })44})45test('fails when height in filename does not match height attribute of SVG', t => {46 return execa(path.resolve(__dirname, '../script/build.js'), ['--input', 'tests/icons/height-mismatch-24.svg'])47 .then(() => {48 t.fail() // Test should fail if execa() call doesn't throw an error49 })50 .catch(error => {51 t.is(error.exitCode, 1)52 t.false(error.killed)53 })54})55test('fails when height attribute is missing', t => {56 return execa(path.resolve(__dirname, '../script/build.js'), ['--input', 'tests/icons/missing-height-attr-16.svg'])57 .then(() => {58 t.fail() // Test should fail if execa() call doesn't throw an error59 })60 .catch(error => {61 t.is(error.exitCode, 1)62 t.false(error.killed)63 })64})65test('fails when width attribute is missing', t => {66 return execa(path.resolve(__dirname, '../script/build.js'), ['--input', 'tests/icons/missing-width-attr-16.svg'])67 .then(() => {68 t.fail() // Test should fail if execa() call doesn't throw an error69 })70 .catch(error => {71 t.is(error.exitCode, 1)72 t.false(error.killed)73 })74})75test('fails when viewBox attribute is missing', t => {76 return execa(path.resolve(__dirname, '../script/build.js'), ['--input', 'tests/icons/missing-viewbox-attr-16.svg'])77 .then(() => {78 t.fail() // Test should fail if execa() call doesn't throw an error79 })80 .catch(error => {81 t.is(error.exitCode, 1)82 t.false(error.killed)83 })84})85test('fails when height attribute is invalid', t => {86 return execa(path.resolve(__dirname, '../script/build.js'), ['--input', 'tests/icons/invalid-height-attr-16.svg'])87 .then(() => {88 t.fail() // Test should fail if execa() call doesn't throw an error89 })90 .catch(error => {91 t.is(error.exitCode, 1)92 t.false(error.killed)93 })94})95test('fails when width attribute is invalid', t => {96 return execa(path.resolve(__dirname, '../script/build.js'), ['--input', 'tests/icons/invalid-width-attr-16.svg'])97 .then(() => {98 t.fail() // Test should fail if execa() call doesn't throw an error99 })100 .catch(error => {101 t.is(error.exitCode, 1)102 t.false(error.killed)103 })104})105test('fails when viewBox attribute is invalid', t => {106 return execa(path.resolve(__dirname, '../script/build.js'), ['--input', 'tests/icons/invalid-viewbox-attr-16.svg'])107 .then(() => {108 t.fail() // Test should fail if execa() call doesn't throw an error109 })110 .catch(error => {111 t.is(error.exitCode, 1)112 t.false(error.killed)113 })114})115test('fails when viewBox width does not match width attribute', t => {116 return execa(path.resolve(__dirname, '../script/build.js'), ['--input', 'tests/icons/viewbox-width-mismatch-16.svg'])117 .then(() => {118 t.fail() // Test should fail if execa() call doesn't throw an error119 })120 .catch(error => {121 t.is(error.exitCode, 1)122 t.false(error.killed)123 })124})125test('fails when viewBox height does not match height attribute', t => {126 return execa(path.resolve(__dirname, '../script/build.js'), ['--input', 'tests/icons/viewbox-height-mismatch-16.svg'])127 .then(() => {128 t.fail() // Test should fail if execa() call doesn't throw an error129 })130 .catch(error => {131 t.is(error.exitCode, 1)132 t.false(error.killed)133 })134})135test('ignores non-SVG input files', t => {136 return execa(path.resolve(__dirname, '../script/build.js'), ['--input', 'tests/build.js'])137 .then(() => {138 t.fail() // Test should fail if execa() call doesn't throw an error139 })140 .catch(error => {141 t.is(error.exitCode, 1)142 t.false(error.killed)143 })...
test.js
Source:test.js
1const test = require("ava");2const execa = require("execa");3const os = require("os");4const path = require("path");5const fs = require("fs-extra");6const bin = "../bin/wallpaper.js";7const _cache = path.join(process.env.HOME, ".wallpaper", ".cache.json");8let cacheBefore = "";9const temp = path.join(__dirname, "./test_images/test3.jpg");10test.before(async t => {11 try {12 cacheBefore = await fs.readFile(_cache, "utf8");13 } catch (error) {14 // console.log(error);15 }16});17test.beforeEach(async t => {18 await execa.stdout(bin, ["update", temp], {19 cwd: __dirname20 });21});22test.after(async t => {23 if (!!cacheBefore) {24 await fs.writeFile(_cache, cacheBefore);25 await execa.stdout(bin, ["switch", "-l"], {26 cwd: __dirname27 });28 } else {29 await fs.unlink(_cache);30 }31});32test.serial("get", async t => {33 t.true((await execa.stdout(bin, ["get"], { cwd: __dirname })).length > 0);34});35test.serial("switch", async t => {36 const orignalImagePath = await execa.stdout(bin, ["get"], {37 cwd: __dirname38 });39 const testImagsPaths = [40 path.join(__dirname, "./test_images/test1.jpg"),41 path.join(__dirname, "./test_images/test2.jpg")42 ];43 await execa.stdout(bin, ["update", testImagsPaths[0]], {44 cwd: __dirname45 });46 await execa.stdout(bin, ["update", testImagsPaths[1]], {47 cwd: __dirname48 });49 await execa.stdout(bin, ["switch", "-p"], {50 cwd: __dirname51 });52 const preImagePath = await execa.stdout(bin, ["get"], {53 cwd: __dirname54 });55 t.true(56 preImagePath.includes(path.resolve(testImagsPaths[0])) &&57 !preImagePath.includes(orignalImagePath)58 );59 await execa.stdout(bin, ["switch", "-n"], {60 cwd: __dirname61 });62 const nextImagePath = await execa.stdout(bin, ["get"], {63 cwd: __dirname64 });65 t.true(66 nextImagePath.includes(path.resolve(testImagsPaths[1])) &&67 !nextImagePath.includes(preImagePath)68 );69 await execa.stdout(bin, ["switch", "-l"], {70 cwd: __dirname71 });72 t.is(await execa.stdout(bin, ["get"], { cwd: __dirname }), nextImagePath);73});74test.serial("update", async t => {75 const tempImagePath = path.join(__dirname, "./test_images/test1.jpg");76 const orignalImagePath = await execa.stdout(bin, ["get"], {77 cwd: __dirname78 });79 await execa.stdout(bin, ["update", tempImagePath], {80 cwd: __dirname81 });82 const updateImagePath = await execa.stdout(bin, ["get"], {83 cwd: __dirname84 });85 t.true(86 updateImagePath.includes(path.resolve(tempImagePath)) &&87 !updateImagePath.includes(orignalImagePath)88 );89});90test.serial("daily:bing", async t => {91 const orignalImagePath = await execa.stdout(bin, ["get"], {92 cwd: __dirname93 });94 await execa.stdout(bin, ["daily", "bing"], {95 cwd: __dirname96 });97 const randomImagePath = await execa.stdout(bin, ["get"], {98 cwd: __dirname99 });100 t.true(101 randomImagePath.includes(os.tmpdir()) &&102 !randomImagePath.includes(orignalImagePath)103 );104});105test.serial("daily:unsplash", async t => {106 const orignalImagePath = await execa.stdout(bin, ["get"], {107 cwd: __dirname108 });109 await execa.stdout(bin, ["daily", "unsplash"], {110 cwd: __dirname111 });112 const randomImagePath = await execa.stdout(bin, ["get"], {113 cwd: __dirname114 });115 t.true(116 randomImagePath.includes(os.tmpdir()) &&117 !randomImagePath.includes(orignalImagePath)118 );119});120test.serial("random:unsplash", async t => {121 const orignalImagePath = await execa.stdout(bin, ["get"], {122 cwd: __dirname123 });124 await execa.stdout(bin, ["random", "unsplash"], {125 cwd: __dirname126 });127 const randomImagePath = await execa.stdout(bin, ["get"], {128 cwd: __dirname129 });130 t.true(131 randomImagePath.includes(os.tmpdir()) &&132 !randomImagePath.includes(orignalImagePath)133 );134});135test.serial("random:bing", async t => {136 const orignalImagePath = await execa.stdout(bin, ["get"], {137 cwd: __dirname138 });139 await execa.stdout(bin, ["random", "bing"], {140 cwd: __dirname141 });142 const randomImagePath = await execa.stdout(bin, ["get"], {143 cwd: __dirname144 });145 t.true(146 randomImagePath.includes(os.tmpdir()) &&147 !randomImagePath.includes(orignalImagePath)148 );149});150test.serial("random:netbian", async t => {151 const orignalImagePath = await execa.stdout(bin, ["get"], {152 cwd: __dirname153 });154 await execa.stdout(bin, ["random", "netbian"], {155 cwd: __dirname156 });157 const randomImagePath = await execa.stdout(bin, ["get"], {158 cwd: __dirname159 });160 t.true(161 randomImagePath.includes(os.tmpdir()) &&162 !randomImagePath.includes(orignalImagePath)163 );...
linkDependencies.js
Source:linkDependencies.js
...14async function run() {15 /**16 * Link shopware-6-client17 */18 await execa("yarn", ["link"], {19 stdio: "inherit",20 cwd: apiClientDir,21 });22 await execa("yarn", ["link", "@shopware-pwa/shopware-6-client"], {23 stdio: "inherit",24 cwd: defaultThemeDir,25 });26 await execa("yarn", ["link", "@shopware-pwa/shopware-6-client"], {27 stdio: "inherit",28 cwd: cliDir,29 });30 /**31 * Link composables32 */33 await execa("yarn", ["link"], {34 stdio: "inherit",35 cwd: composablesDir,36 });37 await execa("yarn", ["link", "@shopware-pwa/composables"], {38 stdio: "inherit",39 cwd: defaultThemeDir,40 });41 /**42 * Link helpers43 */44 await execa("yarn", ["link"], {45 stdio: "inherit",46 cwd: helpersDir,47 });48 await execa("yarn", ["link", "@shopware-pwa/helpers"], {49 stdio: "inherit",50 cwd: defaultThemeDir,51 });52 await execa("yarn", ["link", "@shopware-pwa/helpers"], {53 stdio: "inherit",54 cwd: composablesDir,55 });56 /**57 * Link commons58 */59 await execa("yarn", ["link"], {60 stdio: "inherit",61 cwd: commonsDir,62 });63 await execa("yarn", ["link", "@shopware-pwa/commons"], {64 stdio: "inherit",65 cwd: apiClientDir,66 });67 await execa("yarn", ["link", "@shopware-pwa/commons"], {68 stdio: "inherit",69 cwd: helpersDir,70 });71 await execa("yarn", ["link", "@shopware-pwa/commons"], {72 stdio: "inherit",73 cwd: composablesDir,74 });75 /**76 * Link nuxt-module77 */78 await execa("yarn", ["link"], {79 stdio: "inherit",80 cwd: nuxtModuleDir,81 });82 await execa("yarn", ["link", "@shopware-pwa/nuxt-module"], {83 stdio: "inherit",84 cwd: cliDir,85 });86 /**87 * Link CLI dir88 */89 await execa("yarn", ["link"], {90 stdio: "inherit",91 cwd: cliDir,92 });93 await execa("yarn", ["link", "@shopware-pwa/cli"], {94 stdio: "inherit",95 cwd: defaultThemeDir,96 });97 /**98 * Link theme-base dir99 */100 await execa("yarn", ["link"], {101 stdio: "inherit",102 cwd: themeBaseDir,103 });104 await execa("yarn", ["link", "@shopware-pwa/theme-base"], {105 stdio: "inherit",106 cwd: defaultThemeDir,107 });108 /**109 * Link default-theme dir110 */111 await execa("yarn", ["link"], {112 stdio: "inherit",113 cwd: defaultThemeDir,114 });115 /**116 * link local storefront-ui117 */118 // await execa("yarn", ["link", "@storefront-ui/vue"], {119 // stdio: "inherit",120 // cwd: defaultThemeDir121 // });122}...
Using AI Code Generation
1import { execa } from 'cypress/types/sinon';2describe('My First Test', () => {3 it('Visits the Kitchen Sink', () => {4 cy.contains('type').click()5 cy.url().should('include', '/commands/actions')6 cy.get('.action-email')7 .type('fake@email')8 .should('have.value', 'fake@email')9 })10})11import { execa } from 'cypress/types/sinon';12describe('My First Test', () => {13 it('Visits the Kitchen Sink', () => {14 cy.contains('type').click()15 cy.url().should('include', '/commands/actions')16 cy.get('.action-email')17 .type('fake@email')18 .should('have.value', 'fake@email')19 })20})21import { execa } from 'cypress/types/sinon';22describe('My First Test', () => {23 it('Visits the Kitchen Sink', () => {24 cy.contains('type').click()25 cy.url().should('include', '/commands/actions')26 cy.get('.action-email')27 .type('fake@email')28 .should('have.value', 'fake@email')29 })30})31import { execa } from 'cypress/types/sinon';32describe('My First Test', () => {33 it('Visits the Kitchen Sink', () => {34 cy.contains('type').click()35 cy.url().should
Using AI Code Generation
1const execa = require('execa');2describe('test', () => {3 it('test', async () => {4 const { stdout } = await execa('ls');5 console.log(stdout);6 });7});
Using AI Code Generation
1const execa = require('execa');2const cypress = require('cypress');3const { resolve } = require('path');4const { readdirSync } = require('fs');5const { green, red } = require('chalk');6const { get } = require('lodash');7const { getTestFiles } = require('./utils');8const { CYPRESS_CONFIG_PATH } = process.env;9const cypressConfig = require(resolve(CYPRESS_CONFIG_PATH));10const { testFiles } = cypressConfig;11const testFilesToRun = getTestFiles(testFiles);12const runCypress = async (testFiles) => {13 const { totalFailed } = await cypress.run({14 });15 if (totalFailed > 0) {16 throw new Error(`${totalFailed} test(s) failed`);17 }18};19const runTest = async (testFile) => {20 try {21 await runCypress(testFile);22 console.log(green(`Test ${testFile} passed`));23 } catch (e) {24 console.log(red(`Test ${testFile} failed`));25 throw e;26 }27};28const runTests = async (testFiles) => {29 try {30 await runCypress(testFiles);31 console.log(green(`Tests ${testFiles} passed`));32 } catch (e) {33 console.log(red(`Tests ${testFiles} failed`));34 throw e;35 }36};37const runAllTests = async () => {38 try {39 await runCypress();40 console.log(green(`All tests passed`));41 } catch (e) {42 console.log(red(`All tests failed`));43 throw e;44 }45};46const runTestsInParallel = async (testFiles) => {47 try {48 const promises = testFiles.map((testFile) => runTest(testFile));49 await Promise.all(promises);50 console.log(green(`All tests passed`));51 } catch (e) {52 console.log(red(`All tests failed`));53 throw e;54 }55};56const runTestsInParallel = async (testFiles) => {57 try {58 const promises = testFiles.map((testFile) => runTest(testFile));59 await Promise.all(promises);60 console.log(green(`All tests passed`));61 } catch (e) {
Using AI Code Generation
1const execa = require('execa')2const cypress = require('cypress')3const path = require('path')4const runCypress = () => {5 const cypressBin = path.join(6 return execa(cypressBin, cypressOptions, { stdio: 'inherit' })7}8runCypress()9 .then(() => {10 console.log('Cypress tests are done')11 })12 .catch(err => {13 console.error('Cypress tests failed', err)14 process.exit(1)15 })
Cypress is a renowned Javascript-based open-source, easy-to-use end-to-end testing framework primarily used for testing web applications. Cypress is a relatively new player in the automation testing space and has been gaining much traction lately, as evidenced by the number of Forks (2.7K) and Stars (42.1K) for the project. LambdaTest’s Cypress Tutorial covers step-by-step guides that will help you learn from the basics till you run automation tests on LambdaTest.
You can elevate your expertise with end-to-end testing using the Cypress automation framework and stay one step ahead in your career by earning a Cypress certification. Check out our Cypress 101 Certification.
Watch this 3 hours of complete tutorial to learn the basics of Cypress and various Cypress commands with the Cypress testing at LambdaTest.
Get 100 minutes of automation test minutes FREE!!