"lint" command for flipper-pkg tool
Summary: Implemented json schema for flipper plugin package.json and used it for validation in "flipper-pkg lint" command. Nice thing about json schema is that it not only allows to validate json, but also can be referenced using "$schema" property in json so IDEs like VSCode can find it and use for code completion, validation and to show properties documentation. I'm going to deploy the schema as a part of documentation website so it can be referenced as https://fbflipper.com/schemas/plugin-package/v2.json. Also the "$schema" field can be used instead of "specVersion" to determine the specification according to which the plugin is defined. E.g., if specification version 3 would be created, it will be described in schema https://fbflipper.com/schemas/plugin-package/v3.json, etc. Reviewed By: passy Differential Revision: D21228294 fbshipit-source-id: f21351e584ef936a7d6b314436448489691f83a6
This commit is contained in:
committed by
Facebook GitHub Bot
parent
01f8d80402
commit
21c574ac80
@@ -1,12 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
test('tests are working', () => {
|
||||
expect(true).toBeTruthy();
|
||||
});
|
||||
151
desktop/pkg/src/__tests__/runLint.node.ts
Normal file
151
desktop/pkg/src/__tests__/runLint.node.ts
Normal file
@@ -0,0 +1,151 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
import runLint from '../utils/runLint';
|
||||
import fs from 'fs-extra';
|
||||
|
||||
const validPackageJson = {
|
||||
$schema: 'https://fbflipper.com/schemas/plugin-package/v2.json',
|
||||
name: 'flipper-plugin-network',
|
||||
id: 'Network',
|
||||
flipperBundlerEntry: 'index.tsx',
|
||||
main: 'dist/index.js',
|
||||
title: 'Network',
|
||||
description:
|
||||
'Use the Network inspector to inspect outgoing network traffic in your apps.',
|
||||
icon: 'internet',
|
||||
version: '1.0.0',
|
||||
license: 'MIT',
|
||||
keywords: ['network', 'flipper-plugin'],
|
||||
bugs: {
|
||||
email: 'oncall+flipper@xmail.facebook.com',
|
||||
url: 'https://fb.workplace.com/groups/flippersupport/',
|
||||
},
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
jest.mock('fs-extra', () => jest.fn());
|
||||
fs.pathExists = jest.fn().mockResolvedValue(true);
|
||||
fs.pathExistsSync = jest.fn().mockReturnValue(true);
|
||||
fs.lstatSync = jest.fn().mockReturnValue({
|
||||
isFile: function () {
|
||||
return true;
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test('valid package json', async () => {
|
||||
const json = JSON.stringify(validPackageJson);
|
||||
fs.readFile = jest.fn().mockResolvedValue(new Buffer(json));
|
||||
const result = await runLint('dir');
|
||||
expect(result).toBe(null);
|
||||
});
|
||||
|
||||
test('$schema field is required', async () => {
|
||||
const testPackageJson = Object.assign({}, validPackageJson);
|
||||
delete testPackageJson.$schema;
|
||||
const json = JSON.stringify(testPackageJson);
|
||||
fs.readFile = jest.fn().mockResolvedValue(new Buffer(json));
|
||||
const result = await runLint('dir');
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
". should have required property \\"$schema\\" pointing to a supported schema URI, e.g.:
|
||||
{
|
||||
\\"$schema\\": \\"https://fbflipper.com/schemas/plugin-package/v2.json\\",
|
||||
\\"name\\": \\"flipper-plugin-example\\",
|
||||
...
|
||||
}",
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
test('supported schema is required', async () => {
|
||||
const testPackageJson = Object.assign({}, validPackageJson);
|
||||
testPackageJson.$schema =
|
||||
'https://fbflipper.com/schemas/plugin-package/v1.json';
|
||||
const json = JSON.stringify(testPackageJson);
|
||||
fs.readFile = jest.fn().mockResolvedValue(new Buffer(json));
|
||||
const result = await runLint('dir');
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
".$schema should point to a supported schema. Currently supported schemas:
|
||||
- https://fbflipper.com/schemas/plugin-package/v2.json",
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
test('name is required', async () => {
|
||||
const testPackageJson = Object.assign({}, validPackageJson);
|
||||
delete testPackageJson.name;
|
||||
const json = JSON.stringify(testPackageJson);
|
||||
fs.readFile = jest.fn().mockResolvedValue(new Buffer(json));
|
||||
const result = await runLint('dir');
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
". should have required property 'name'",
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
test('name must start with "flipper-plugin-"', async () => {
|
||||
const testPackageJson = Object.assign({}, validPackageJson);
|
||||
testPackageJson.name = 'test-plugin';
|
||||
const json = JSON.stringify(testPackageJson);
|
||||
fs.readFile = jest.fn().mockResolvedValue(new Buffer(json));
|
||||
const result = await runLint('dir');
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"/name should start with \\"flipper-plugin-\\", e.g. \\"flipper-plugin-example\\"",
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
test('keywords must contain "flipper-plugin"', async () => {
|
||||
const testPackageJson = Object.assign({}, validPackageJson);
|
||||
testPackageJson.keywords = ['flipper', 'network'];
|
||||
const json = JSON.stringify(testPackageJson);
|
||||
fs.readFile = jest.fn().mockResolvedValue(new Buffer(json));
|
||||
const result = await runLint('dir');
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"/keywords should contain keyword \\"flipper-plugin\\"",
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
test('flippeBundlerEntry must point to an existing file', async () => {
|
||||
const testPackageJson = Object.assign({}, validPackageJson);
|
||||
testPackageJson.flipperBundlerEntry = 'unexisting/file';
|
||||
fs.pathExistsSync = jest
|
||||
.fn()
|
||||
.mockImplementation((path) => !path.includes('unexisting/file'));
|
||||
const json = JSON.stringify(testPackageJson);
|
||||
fs.readFile = jest.fn().mockResolvedValue(new Buffer(json));
|
||||
const result = await runLint('dir');
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"/flipperBundlerEntry should point to a valid file",
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
test('multiple validation errors reported', async () => {
|
||||
const testPackageJson = Object.assign({}, validPackageJson);
|
||||
testPackageJson.keywords = ['flipper'];
|
||||
delete testPackageJson.flipperBundlerEntry;
|
||||
const json = JSON.stringify(testPackageJson);
|
||||
fs.readFile = jest.fn().mockResolvedValue(new Buffer(json));
|
||||
const result = await runLint('dir');
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
". should have required property 'flipperBundlerEntry'",
|
||||
"/keywords should contain keyword \\"flipper-plugin\\"",
|
||||
]
|
||||
`);
|
||||
});
|
||||
Reference in New Issue
Block a user