Example #1
0
 const fakeEventToPromise = sinon.spy(async (stream) => {
   await defaultEventToPromise(stream, 'close');
   // Remove contents of tmpDir before removal of directory.
   const files = await fs.readdir(tmpDir.path());
   for (const file of files) {
     await fs.unlink(path.join(tmpDir.path(), file));
   }
   return Promise.reject(new Error('Unexpected error'));
 });
Example #2
0
export async function prepareArtifactsDir(
  artifactsDir: string,
  {asyncMkdirp = defaultAsyncMkdirp}: PrepareArtifactsDirOptions = {},
): Promise<string> {
  try {
    const stats = await fs.stat(artifactsDir);
    if (!stats.isDirectory()) {
      throw new UsageError(
        `--artifacts-dir="${artifactsDir}" exists but it is not a directory.`);
    }
    // If the artifactsDir already exists, check that we have the write permissions on it.
    try {
      await fs.access(artifactsDir, fs.W_OK);
    } catch (accessErr) {
      if (isErrorWithCode('EACCES', accessErr)) {
        throw new UsageError(
          `--artifacts-dir="${artifactsDir}" exists but the user lacks ` +
          'permissions on it.');
      } else {
        throw accessErr;
      }
    }
  } catch (error) {
    if (isErrorWithCode('EACCES', error)) {
      // Handle errors when the artifactsDir cannot be accessed.
      throw new UsageError(
        `Cannot access --artifacts-dir="${artifactsDir}" because the user ` +
        `lacks permissions: ${error}`);
    } else if (isErrorWithCode('ENOENT', error)) {
      // Create the artifact dir if it doesn't exist yet.
      try {
        log.debug(`Creating artifacts directory: ${artifactsDir}`);
        await asyncMkdirp(artifactsDir);
      } catch (mkdirErr) {
        if (isErrorWithCode('EACCES', mkdirErr)) {
          // Handle errors when the artifactsDir cannot be created for lack of permissions.
          throw new UsageError(
            `Cannot create --artifacts-dir="${artifactsDir}" because the ` +
            `user lacks permissions: ${mkdirErr}`);
        } else {
          throw mkdirErr;
        }
      }
    } else {
      throw error;
    }
  }

  return artifactsDir;
}
Example #3
0
    return new Promise(async (resolve, reject) => {
      await os.configure();

      console.log('Zipping image for upload');
      const archivePath = `${os.image.path}.zip`;
      zip.file(basename(os.image.path), await fs.readFile(os.image.path));
      const data = zip.generate({ base64: false, compression: 'DEFLATE' });
      await fs.writeFile(archivePath, data, 'binary');

      const progress = new Progress('Flashing image');
      const req = rp.post({ uri: `${this.options.devicePath}/dut/flash` });

      req.catch(error => {
        reject(error);
      });
      req.finally(() => {
        if (lastStatus !== 'done') {
          reject(new Error('Unexpected end of TCP connection'));
        }

        resolve();
      });

      let lastStatus;
      req.on('data', data => {
        const computedLine = RegExp('(.*): (.*)').exec(data.toString());

        if (computedLine) {
          if (computedLine[1] === 'error') {
            req.cancel();
            reject(new Error(computedLine[2]));
          }

          if (computedLine[1] === 'progress') {
            console.log('finally');
            try {
              progress.update(JSON.parse(computedLine[2]));
            } catch (err) {}
          }

          if (computedLine[1] === 'status') {
            lastStatus = computedLine[2];
          }
        }
      });

      await promiseStream(fs.createReadStream(archivePath).pipe(req));
    });
Example #4
0
/*
 * Resolves true if the path is a readable directory.
 *
 * Usage:
 *
 * isDirectory('/some/path')
 *  .then((dirExists) => {
 *    // dirExists will be true or false.
 *  });
 *
 * */
export default function isDirectory(path: string): Promise {
  return fs.stat(path)
    .then((stats) => stats.isDirectory())
    .catch(onlyErrorsWithCode(['ENOENT', 'ENOTDIR'], () => {
      return false;
    }));
}
Example #5
0
export async function getIdFromSourceDir(
  sourceDir: string
): Promise<string | void> {
  const filePath = path.join(sourceDir, extensionIdFile);

  let content;

  try {
    content = await fs.readFile(filePath);
  } catch (error) {
    if (isErrorWithCode('ENOENT', error)) {
      log.debug(`No ID file found at: ${filePath}`);
      return;
    }
    throw error;
  }

  let lines = content.toString().split('\n');
  lines = lines.filter((line) => {
    line = line.trim();
    if (line && !line.startsWith('#')) {
      return line;
    }
  });

  const id = lines[0];
  log.debug(`Found extension ID ${id} in ${filePath}`);

  if (!id) {
    throw new UsageError(`No ID found in extension ID file ${filePath}`);
  }

  return id;
}
Example #6
0
File: index.js Project: koajs/ejs
  /**
   * generate html with view name and options
   * @param {String} view
   * @param {Object} options
   * @return {String} html
   */
  async function render(view, options) {
    view += settings.viewExt;
    const viewPath = path.join(settings.root, view);
    debug(`render: ${viewPath}`);
    // get from cache
    if (settings.cache && cache[viewPath]) {
      return cache[viewPath].call(options.scope, options);
    }

    const tpl = await fs.readFile(viewPath, 'utf8');

    // override `ejs` node_module `resolveInclude` function
    ejs.resolveInclude = function(name, filename, isDir) {
      if (!path.extname(name)) {
        name += settings.viewExt;
      }
      return parentResolveInclude(name, filename, isDir);
    }

    const fn = ejs.compile(tpl, {
      filename: viewPath,
      _with: settings._with,
      compileDebug: settings.debug && settings.compileDebug,
      debug: settings.debug,
      delimiter: settings.delimiter,
      cache: settings.cache,
      async: settings.async
    });
    if (settings.cache) {
      cache[viewPath] = fn;
    }

    return fn.call(options.scope, options);
  }
Example #7
0
  async flash(os) {
    await os.configure();

    if (!this.board.isReady) {
      throw new Error('Board is not marked as ready.');
    }

    await this.off();

    const source = await new sdk.sourceDestination.StreamZipSource(
      new sdk.sourceDestination.SingleUseStreamSource(fs.createReadStream(os.image.path))
    );
    // For linux, udev will provide us with a nice id for the testbot
    const drive = await getDrive(await this.getDevInterface());

    const progressBar = {
      flashing: new visuals.Progress('Flashing'),
      verifying: new visuals.Progress('Validating')
    };

    await sdk.multiWrite.pipeSourceToDestinations(
      source,
      [drive],
      (_destination, error) => {
        console.error(error);
      },
      progress => {
        progressBar[progress.type].update(progress);
      },
      true
    );
  }
Example #8
0
 (tmpDir) => {
   tmpPath = tmpDir.path();
   return fs.stat(tmpPath)
     .then(() => {
       tmpPathExisted = true;
       throw new Error('simulated error');
     });
 })
Example #9
0
 (tmpDir) => {
   const configFilePath = path.join(tmpDir.path(), 'config.js');
   fs.writeFileSync(configFilePath,
     `module.exports = {
       sourceDir: 'path/to/fake/source/dir',
     };`);
   const configObj = loadJSConfigFile(configFilePath);
   assert.equal(configObj.sourceDir, 'path/to/fake/source/dir');
 });
Example #10
0
 (tmpDir) => {
   const sourceDir = tmpDir.path();
   return fs.writeFile(path.join(sourceDir, extensionIdFile), '')
     .then(() => getIdFromSourceDir(sourceDir))
     .then(makeSureItFails())
     .catch(onlyInstancesOf(UsageError, (error) => {
       assert.match(error.message, /No ID found in extension ID file/);
     }));
 }
Example #11
0
 it('returns the package version in production', () => {
   const pkgFile = path.join(projectRoot, 'package.json');
   return fs.readFile(pkgFile)
     .then((pkgData) => {
       const testBuildEnv = {globalEnv: 'production'};
       assert.equal(defaultVersionGetter(projectRoot, testBuildEnv),
                    JSON.parse(pkgData).version);
     });
 });
Example #12
0
      withTempDir(async (tmpDir) => {
        const manifestWithComments = `{
          "name": "the extension",
          "version": "0.0.1" // comments
        }`;
        const manifestFile = path.join(tmpDir.path(), 'manifest.json');
        await fs.writeFile(manifestFile, manifestWithComments);
        const manifestData = await getValidatedManifest(tmpDir.path());

        assert.deepEqual(manifestData, manifestWithoutApps);
      })
Example #13
0
 (tmpDir) => {
   const configFilePath = path.join(tmpDir.path(), 'config.js');
   fs.writeFileSync(configFilePath,
     // missing = in two places
     `module.exports {
         sourceDir 'path/to/fake/source/dir',
       };`);
   assert.throws(() => {
     loadJSConfigFile(configFilePath);
   }, UsageError);
 });
Example #14
0
export async function saveIdToSourceDir(
  sourceDir: string, id: string
): Promise<void> {
  const filePath = path.join(sourceDir, extensionIdFile);
  await fs.writeFile(filePath, [
    '# This file was created by https://github.com/mozilla/web-ext',
    '# Your auto-generated extension ID for addons.mozilla.org is:',
    id.toString(),
  ].join('\n'));

  log.debug(`Saved auto-generated ID ${id} to ${filePath}`);
}
 test('handles bundle tagged-template literals in ES5', () => __awaiter(this, void 0, void 0, function* () {
     const tmpDir = tmp.dirSync();
     copyDir(path.join(util_1.fixtureDir, 'build-with-tagged-template-literals', 'source'), tmpDir.name);
     yield run_command_1.runCommand(binPath, ['build'], {
         cwd: tmpDir.name,
     });
     const filename = path.join(tmpDir.name, 'build', 'es5-bundled', 'my-app.html');
     const contents = mz_1.fs.readFileSync(filename, 'utf-8');
     // assert contents contain _templateObject with UUID suffix
     chai_1.assert.match(contents, /_templateObject\d*_[A-Fa-f0-9]+\s*=/g, 'build output does not contain modified _templateObject names');
     // assert contents don't contain unmodified "_templateObject" variable
     chai_1.assert.notMatch(contents, /_templateObject\d*\s*=/g, 'build output contains unmodified _templateObject names');
 }));
Example #16
0
 (tmpDir) => {
   let badManifest = `{
     "name": "I'm an invalid JSON Manifest
     "version": "0.0.0"
   }`;
   let manifestFile = path.join(tmpDir.path(), 'manifest.json');
   return fs.writeFile(manifestFile, badManifest)
     .then(() => getValidatedManifest(tmpDir.path()))
     .then(makeSureItFails())
     .catch(onlyInstancesOf(InvalidManifest, (error) => {
       assert.match(error.message, /Error parsing manifest\.json/);
       assert.include(error.message, manifestFile);
     }));
 }
function assertDirsEqual(actual, expected, basedir = actual) {
    if (process.env['UPDATE_POLYMER_CLI_GOLDENS']) {
        fsExtra.emptyDirSync(expected);
        fsExtra.copySync(actual, expected);
        throw new Error('Goldens updated, test failing for your saftey.');
    }
    const actualNames = mz_1.fs.readdirSync(actual).sort();
    const expectedNames = mz_1.fs.readdirSync(expected).sort();
    chai_1.assert.deepEqual(actualNames, expectedNames, `expected files in directory ${path.relative(basedir, actual)}`);
    for (const fn of actualNames) {
        const subActual = path.join(actual, fn);
        const subExpected = path.join(expected, fn);
        const stat = mz_1.fs.statSync(subActual);
        if (stat.isDirectory()) {
            assertDirsEqual(subActual, subExpected, basedir);
        }
        else {
            const actualContents = mz_1.fs.readFileSync(subActual, 'utf-8').trim();
            const expectedContents = mz_1.fs.readFileSync(subExpected, 'utf-8').trim();
            chai_1.assert.deepEqual(actualContents, expectedContents, `expected contents of ${path.relative(basedir, subActual)}`);
        }
    }
}
Example #18
0
 (tmpDir) => {
   const testFileName = path.join(tmpDir.path(),
                                  'minimal_extension-1.0.zip');
   return fs.writeFile(testFileName, 'test')
     .then(() => build(
       {
         sourceDir: fixturePath('minimal-web-ext'),
         artifactsDir: tmpDir.path(),
         overwriteDest: true,
       }))
     .then((buildResult) => {
       assert.match(buildResult.extensionPath,
                    /minimal_extension-1\.0\.zip$/);
     });
 });
Example #19
0
 (tmpDir) => {
   const testFileName = path.join(tmpDir.path(),
                                  'minimal_extension-1.0.zip');
   return fs.writeFile(testFileName, 'test')
     .then(() => build(
       {
         sourceDir: fixturePath('minimal-web-ext'),
         artifactsDir: tmpDir.path(),
       }))
     .catch ((error) => {
       assert.instanceOf(error, UsageError);
       assert.match(error.message,
                    /Extension exists at the destination path/);
     });
 });
Example #20
0
      withTempDir(async (tmpDir) => {
        const invalidManifestWithComments = `{
          // a comment in its own line
          // another comment on its own line
          "name": "I'm an invalid JSON Manifest
        }`;
        const manifestFile = path.join(tmpDir.path(), 'manifest.json');
        await fs.writeFile(manifestFile, invalidManifestWithComments);
        const promise = getValidatedManifest(tmpDir.path());

        const error = await assert.isRejected(promise, InvalidManifest);
        await assert.isRejected(promise, /Error parsing manifest\.json at /);
        assert.include(error.message, 'in JSON at position 133');
        assert.include(error.message, manifestFile);
      })
Example #21
0
 (tmpDir) => {
   const messageFileName = path.join(tmpDir.path(), 'messages.json');
   fs.writeFileSync(messageFileName,
     '{"simulated:" "json syntax error"');
   return getDefaultLocalizedName({
     messageFile: messageFileName,
     manifestData: manifestWithoutApps,
   })
     .then(makeSureItFails())
     .catch((error) => {
       assert.instanceOf(error, UsageError);
       assert.match(error.message, /Unexpected token '"' at 1:15/);
       assert.match(error.message, /^Error parsing messages.json/);
       assert.include(error.message, messageFileName);
     });
 }
    process(req, res, next, done) {
        const path = req.path;

        fs.readFile(path)
            .then((data) => {
                res.status(200);
                res.setBody(data);

                next();
            })
            .catch((error) => {
                res.status(404);

                done();
            });
    }
Example #23
0
/*
 * Resolves true if the path is a readable file.
 *
 * Usage:
 *
 * const exists = await fileExists(filePath);
 * if (exists) {
 *   // ...
 * }
 *
 * */
export default async function fileExists(
  path: string,
  {
    fileIsReadable = (f) => fs.access(f, fs.constants.R_OK),
  }: FileExistsOptions = {}
): Promise<boolean> {
  try {
    await fileIsReadable(path);
    const stat = await fs.stat(path);
    return stat.isFile();
  } catch (error) {
    if (isErrorWithCode(['EACCES', 'ENOENT'], error)) {
      return false;
    }
    throw error;
  }
}
Example #24
0
        .then((buildResult) => {
          assert.equal(onSourceChange.called, true);
          const args = onSourceChange.firstCall.args[0];
          assert.equal(args.sourceDir, sourceDir);
          assert.equal(args.artifactsDir, artifactsDir);
          assert.typeOf(args.onChange, 'function');

          // Make sure it uses the file filter.
          assert.typeOf(args.shouldWatchFile, 'function');
          args.shouldWatchFile('/some/path');
          assert.equal(fileFilter.wantFile.called, true);

          // Remove the built extension.
          return fs.unlink(buildResult.extensionPath)
            // Execute the onChange handler to make sure it gets built
            // again. This simulates what happens when the file watcher
            // executes the callback.
            .then(() => args.onChange());
        })
Example #25
0
export default function getValidatedManifest(sourceDir: string): Promise {
  let manifestFile = path.join(sourceDir, 'manifest.json');
  log.debug(`Validating manifest at ${manifestFile}`);
  return fs.readFile(manifestFile)
    .catch((error) => {
      throw new InvalidManifest(
        `Could not read manifest.json file at ${manifestFile}: ${error}`);
    })
    .then((manifestContents) => JSON.parse(manifestContents))
    .catch((error) => {
      throw new InvalidManifest(
        `Error parsing manifest.json at ${manifestFile}: ${error}`);
    })
    .then((manifestData) => {
      let errors = [];
      // This is just some basic validation of what web-ext needs, not
      // what Firefox will need to run the extension.
      // TODO: integrate with the addons-linter for actual validation.
      if (!manifestData.name) {
        errors.push('missing "name" property');
      }
      if (!manifestData.version) {
        errors.push('missing "version" property');
      }

      if (manifestData.applications && !manifestData.applications.gecko) {
        // Since the applications property only applies to gecko, make
        // sure 'gecko' exists when 'applications' is defined. This should
        // make introspection of gecko properties easier.
        errors.push('missing "applications.gecko" property');
      }

      if (errors.length) {
        throw new InvalidManifest(
          `Manifest at ${manifestFile} is invalid: ${errors.join('; ')}`);
      }
      return manifestData;
    });
}
Example #26
0
      (tmpDir) => {
        const messageFileName = path.join(tmpDir.path(), 'messages.json');
        fs.writeFileSync(messageFileName,
          `{"extensionName": {
              "message": "example extension",
              "description": "example description"
            }
          }`);

        const manifestWithRepeatingPattern = {
          name: '__MSG_extensionName__ __MSG_extensionName__',
          version: '0.0.1',
        };

        return getDefaultLocalizedName({
          messageFile: messageFileName,
          manifestData: manifestWithRepeatingPattern,
        })
          .then((result) => {
            assert.match(result, /example extension example extension/);
          });
      }
Example #27
0
 (tmpDir) => {
   const sourceDir = path.join(tmpDir.path(), 'source-dir');
   const customId = 'some-custom-id';
   const stubs = getStubs();
   // First, save an extension ID like a previous signing call.
   return fs.mkdir(sourceDir)
     .then(() => saveIdToSourceDir(sourceDir, 'some-other-id'))
     // Now, make a signing call with a custom ID.
     .then(() => sign(tmpDir, stubs, {
       extraArgs: {
         sourceDir,
         id: customId,
       },
       extraOptions: {
         preValidatedManifest: manifestWithoutApps,
       },
     }))
     .then(() => {
       sinon.assert.called(stubs.signAddon);
       sinon.assert.calledWithMatch(stubs.signAddon, {id: customId});
     });
 }
Example #28
0
    (tmpDir) => {
      const artifactsDir = path.join(tmpDir.path(), 'web-ext-artifacts');
      const someFile = path.join(tmpDir.path(), 'foo.txt');

      var resolveChange;
      const whenFilesChanged = new Promise((resolve) => {
        resolveChange = resolve;
      });
      const onChange = sinon.spy(() => {
        resolveChange();
      });

      return fs.writeFile(someFile, '<contents>')
        .then(() => {
          return onSourceChange({
            sourceDir: tmpDir.path(),
            artifactsDir,
            onChange,
            shouldWatchFile: () => true,
          });
        })
        .then((watcher) => {
          return fs.utimes(someFile, Date.now() / 1000, Date.now() / 1000)
            .then(() => watcher);
        })
        .then((watcher) => {
          return whenFilesChanged
            .then(() => {
              watcher.close();
              assert.equal(onChange.callCount, 1);
              // This delay seems to avoid stat errors from the watcher
              // which can happen when the temp dir is deleted (presumably
              // before watcher.close() has removed all listeners).
              return new Promise((resolve) => setTimeout(resolve, 2));
            });
        });
    }
Example #29
0
 (tmpDir) => {
   const messageFileName = path.join(tmpDir.path(), 'messages.json');
   //This is missing the 'message' key
   fs.writeFileSync(messageFileName,
     `{"extensionName": {
         "description": "example extension"
         }
     }`);
   const basicLocalizedManifest = {
     name: '__MSG_extensionName__',
     version: '0.0.1',
   };
   return getDefaultLocalizedName({
     messageFile: messageFileName,
     manifestData: basicLocalizedManifest,
   })
     .then(makeSureItFails())
     .catch((error) => {
       assert.instanceOf(error, UsageError);
       assert.match(
         error.message,
         /The locale file .*messages\.json is missing key: extensionName/);
     });
 }
Example #30
0
 .then((watcher) => {
   return fs.utimes(someFile, Date.now() / 1000, Date.now() / 1000)
     .then(() => watcher);
 })