Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Various improvements #9

Merged
merged 8 commits into from
Aug 24, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ branches:

env:
matrix:
- SEQ_VERSION=4
- SEQ_VERSION=5
- SEQUELIZE_VERSION=4
- SEQUELIZE_VERSION=5

global:
- TEST=1
Expand All @@ -31,7 +31,7 @@ matrix:
env: TEST=0 COVERAGE=1

before_script:
- sh -c "if [ '$TEST' = '1' ]; then npm install sequelize@^$SEQ_VERSION.0.0; fi"
- sh -c "if [ '$TEST' = '1' ]; then npm install sequelize@^$SEQUELIZE_VERSION.0.0; fi"

script:
- sh -c "if [ '$TEST' = '1' ]; then npm run test; fi"
Expand Down
91 changes: 11 additions & 80 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,84 +1,15 @@
# Contributing
# Contributions Welcome

## Guidelines
## PR Guidelines

- [Directory structure for Javascript/Node modules](https://gist.github.com/tracker1/59f2c13044315f88bee9#file-01-directory-structure-md)
- scoped pull requests (related changes only)
- make sure existing tests pass
- add new tests if new functionality is added

## Issues
## Uses

Feel free to [open an issue](https://github.com/amercier/npm-package-skeleton/issues/new),
or propose a [pull request](https://github.com/amercier/npm-package-skeleton/pulls).
To prevent duplication, please look at [existing issues](https://github.com/amercier/npm-package-skeleton/issues?q=is%3Aissue) before posting a new one.

## TL;DR

| Command | Description |
| -------------- | ---------------------------------------------------------------------------------------------------------- |
| `npm test` | Runs test suite once using [Jest](http://jestjs.io/). |
| `npm start` | Runs test once, watch for changes in dev/test files, then re-runs tests automatically when a file changes. |
| `npm run lint` | Runs [ESLint](https://eslint.org/) linter. |

## Getting started

#### Step 1. Checkout repository

_**Prerequisites:** you need to have `git`, `node` (>=6) and `npm` installed_.

```bash
git clone https://github.com/amercier/npm-package-skeleton.git
```

_(or your clone's Git URL)_

#### Step 2. Install NPM dependencies

```bash
npm install
```

#### Step 3. Run tests (run-once mode)

```bash
npm test
```

```log
> package-skeleton@1.0.4 test ./npm-package-skeleton
> jest

PASS specs/lib/index.spec.js
myModule
✓ exists (4ms)
✓ returns true

Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 0.558s, estimated 1s
Ran all test suites.
```

**Note:** Use `npm test -- --coverage` to generate code coverage report in the `coverage` directory, and `open coverage/index.html` to view full HTML report.

#### Step 4. Run tests (TDD mode)

```bash
npm start
```

## Coding standards

This project follows [Airbnb Javascript Style Guide](https://github.com/airbnb/javascript). It is enforced at build time by [ESLint](http://eslint.org/).

```bash
npm lint
```

**Note:** this is automatically run before the test suite by `npm test`, but not by `npm start`

## Other commands

| Command | Description |
| --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `npm run doc` | Generates API documentation in `esdoc` folder. Not expected to be run manually, since [ESDoc](https://esdoc.org/) hosting service runs it already. |
| `npm run build` | Transpile all files from `src` directory to `dist`, using [Babel](https://babeljs.io/). Not expected to be run manually, since it is automatically run before NPM packaging (`package.json`'s `prepublishOnly` script). |
- Husky (pre-commit hooks)
- ESlint with the [Airbnb Style Guide](https://github.com/airbnb/javascript)
- Prettier (recommended and unicorn/recommended)
- Jest
- JSDocs
8 changes: 7 additions & 1 deletion lib/schema-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -439,12 +439,18 @@ class SchemaManager {
* @returns {string}
*/
_getAttributeExamples(attributeName, attributeProperties) {
// skip if user has not defined examples
if (!this.constructor._hasCustomAttributeProperty(attributeProperties, 'examples')) {
return null; // user has not defined examples
return null;
}

const { examples } = attributeProperties.jsonSchema;

// see https://json-schema.org/understanding-json-schema/reference/generic.html
if (!Array.isArray(examples)) {
throw new TypeError("The 'examples' property MUST be an array");
}

return _strategy.get(this).getPropertyExamples(examples);
}
}
Expand Down
10 changes: 0 additions & 10 deletions lib/strategies/json-schema-v7.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,6 @@ const StrategyInterface = require('../strategy-interface');
* @augments StrategyInterface
*/
class JsonSchema7Strategy extends StrategyInterface {
/**
* Returns the full URI to the online JSON Schema v7 schema (validation) file.
*
* @example https://json-schema.org/draft-07/schema#
* @returns {string}
*/
getOnlineSchemaUri() {
return 'https://json-schema.org/draft-07/schema#';
}

/**
* Returns the "$schema" property.
*
Expand Down
14 changes: 0 additions & 14 deletions lib/strategies/openapi-v3.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,6 @@ const StrategyInterface = require('../strategy-interface');
* @augments StrategyInterface
*/
class OpenApi3Strategy extends StrategyInterface {
/**
* Returns the full URI to the online OpenAPI v3 schema (validation) file.
*
* @example https://raw.githubusercontent.com/OAI/OpenAPI-Specification/master/schemas/v3.0/schema.json
* @returns {string}
*/
getOnlineSchemaUri() {
return 'https://raw.githubusercontent.com/OAI/OpenAPI-Specification/master/schemas/v3.0/schema.json';
}

/**
* Returns null because OpenAPI 3.0 does not support the "schema" property.
*
Expand Down Expand Up @@ -82,10 +72,6 @@ class OpenApi3Strategy extends StrategyInterface {
* @returns {object}
*/
getPropertyExamples(examples) {
if (!Array.isArray(examples)) {
throw new TypeError("OpenAPI 3.0 requires type 'array' for the 'example' property");
}

return {
example: examples,
};
Expand Down
14 changes: 4 additions & 10 deletions lib/strategy-interface.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,6 @@
* @license Licensed under the MIT License
*/
class StrategyInterface {
/**
* Must return the full URI to the strategy-specific online json (validation) schema.
*
* @returns {string}
*/
getOnlineSchemaUri() {
this.constructor._throwMissingImplementationError(this.constructor.name, 'getOnlineSchemaUri');
}

/**
* Must return the property used as "schema".
*
Expand Down Expand Up @@ -78,7 +69,10 @@ class StrategyInterface {
* @returns {object}
*/
convertTypePropertyToAllowNull(type) {
this.constructor._throwMissingImplementationError(this.constructor.name, 'getNullableType');
this.constructor._throwMissingImplementationError(
this.constructor.name,
'convertTypePropertyToAllowNull',
);
}

/**
Expand Down
9 changes: 8 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@
"lcov",
"text",
"html"
],
"collectCoverageFrom": [
"./lib/**/*"
]
},
"prettier": {
Expand Down Expand Up @@ -159,7 +162,11 @@
},
"release-it": {
"github": {
"release": true
"release": true,
"changelog": "npx auto-changelog --stdout --commit-limit false -u"
},
"hooks": {
"after:bump": "npx auto-changelog -p"
}
}
}
54 changes: 26 additions & 28 deletions test/strategy-interface.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
const models = require('./models');
const { SchemaManager } = require('../lib');
const StrategyInterface = require('../lib/strategy-interface');

// create a dummy strategy so we can test non-implemented methods
Expand All @@ -13,69 +11,69 @@ describe('StrategyInterface', function() {
describe('Ensure we are testing against:', function() {
const methodCount = Object.getOwnPropertyNames(StrategyInterface.prototype).length - 1; // excluding the constructor

it(`9 interface methods`, function() {
expect(methodCount).toEqual(9);
it(`8 interface methods`, function() {
expect(methodCount).toEqual(8);
});
});

// ------------------------------------------------------------------------
// test missing methods in the extended class
// ------------------------------------------------------------------------
describe('Ensure exceptions are thrown if child class has not implemented:', function() {
const schemaManager = new SchemaManager();

it('getOnlineSchemaUri()', function() {
expect(() => {
schemaManager.generate(models.user, dummyStrategy);
}).toThrow(Error);
});

it('getPropertySchema()', function() {
expect(() => {
schemaManager.generate(models.user, dummyStrategy);
}).toThrow(Error);
dummyStrategy.getPropertySchema();
}).toThrow("DummyStrategy has not implemented the 'getPropertySchema' interface method.");
});

it('getPropertyId()', function() {
expect(() => {
schemaManager.generate(models.user, dummyStrategy);
}).toThrow(Error);
dummyStrategy.getPropertyId();
}).toThrow("DummyStrategy has not implemented the 'getPropertyId' interface method.");
});

it('getPropertyTitle()', function() {
expect(() => {
schemaManager.generate(models.user, dummyStrategy);
}).toThrow(Error);
dummyStrategy.getPropertyTitle();
}).toThrow("DummyStrategy has not implemented the 'getPropertyTitle' interface method.");
});

it('getPropertyDescription()', function() {
expect(() => {
schemaManager.generate(models.user, dummyStrategy);
}).toThrow(Error);
dummyStrategy.getPropertyDescription();
}).toThrow(
"DummyStrategy has not implemented the 'getPropertyDescription' interface method.",
);
});

it('getPropertyExamples()', function() {
expect(() => {
schemaManager.generate(models.user, dummyStrategy);
}).toThrow(Error);
dummyStrategy.getPropertyExamples();
}).toThrow("DummyStrategy has not implemented the 'getPropertyExamples' interface method.");
});

it('convertTypePropertyToAllowNull()', function() {
expect(() => {
schemaManager.generate(models.user, dummyStrategy);
}).toThrow(Error);
dummyStrategy.convertTypePropertyToAllowNull();
}).toThrow(
"DummyStrategy has not implemented the 'convertTypePropertyToAllowNull' interface method.",
);
});

it('getPropertyForHasOneAssociation()', function() {
expect(() => {
schemaManager.generate(models.user, dummyStrategy);
}).toThrow(Error);
dummyStrategy.getPropertyForHasOneAssociation();
}).toThrow(
"DummyStrategy has not implemented the 'getPropertyForHasOneAssociation' interface method.",
);
});

it('getPropertyForHasManyAssociation()', function() {
expect(() => {
schemaManager.generate(models.user, dummyStrategy);
}).toThrow(Error);
dummyStrategy.getPropertyForHasManyAssociation();
}).toThrow(
"DummyStrategy has not implemented the 'getPropertyForHasManyAssociation' interface method.",
);
});
});
});