Skip to content

Commit 5ca373b

Browse files
authored
feat: validation of plugin options (#45)
Validation of plugin options through the use of Gatsby Node API's `pluginOptionsSchema`. closes #39
1 parent d0d11b0 commit 5ca373b

File tree

2 files changed

+90
-0
lines changed

2 files changed

+90
-0
lines changed

plugin/gatsby-node.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,24 @@ const { newCloudinary, getResourceOptions } = require('./utils');
33
const REPORTER_PREFIX = `gatsby-source-cloudinary`;
44
const NODE_TYPE = `CloudinaryMedia`;
55

6+
exports.pluginOptionsSchema = ({ Joi }) => {
7+
return Joi.object({
8+
cloudName: Joi.string().required(),
9+
apiKey: Joi.string().required(),
10+
apiSecret: Joi.string().required(),
11+
resourceType: Joi.string().default('image'),
12+
type: Joi.string().default('all'),
13+
maxResults: Joi.number().integer().positive().default(10),
14+
resultsPerPage: Joi.number()
15+
.integer()
16+
.positive()
17+
.default(Joi.ref('maxResults')),
18+
tags: Joi.boolean().default(false),
19+
prefix: Joi.string(),
20+
context: Joi.boolean(),
21+
});
22+
};
23+
624
const getNodeData = (gatsbyUtils, media, cloudName) => {
725
const { createNodeId, createContentDigest } = gatsbyUtils;
826

plugin/gatsby-node.test.js

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import Joi from 'joi';
2+
import { testPluginOptionsSchema } from 'gatsby-plugin-utils';
3+
import { pluginOptionsSchema } from './gatsby-node';
4+
5+
describe('pluginOptionsSchema', () => {
6+
test('should validate minimal correct options', async () => {
7+
const options = {
8+
cloudName: 'cloudName',
9+
apiKey: 'apiKey',
10+
apiSecret: 'apiSecret',
11+
};
12+
13+
const { isValid } = await testPluginOptionsSchema(
14+
pluginOptionsSchema,
15+
options,
16+
);
17+
18+
expect(isValid).toBe(true);
19+
});
20+
21+
test('should invalidate incorrect options', async () => {
22+
const options = {
23+
cloudName: 120,
24+
apiKey: '',
25+
resourceType: '',
26+
type: 30,
27+
maxResults: '',
28+
resultsPerPage: 'hello',
29+
tags: 'world',
30+
prefix: 800,
31+
context: '',
32+
};
33+
34+
const { isValid, errors } = await testPluginOptionsSchema(
35+
pluginOptionsSchema,
36+
options,
37+
);
38+
39+
expect(isValid).toBe(false);
40+
expect(errors).toEqual([
41+
`"cloudName" must be a string`,
42+
`"apiKey" is not allowed to be empty`,
43+
`"apiSecret" is required`,
44+
`"resourceType" is not allowed to be empty`,
45+
`"type" must be a string`,
46+
`"maxResults" must be a number`,
47+
`"resultsPerPage" must be a number`,
48+
`"tags" must be a boolean`,
49+
`"prefix" must be a string`,
50+
`"context" must be a boolean`,
51+
]);
52+
});
53+
54+
test('should add defaults', async () => {
55+
const schema = pluginOptionsSchema({ Joi });
56+
const options = {
57+
cloudName: 'cloudName',
58+
apiKey: 'apiKey',
59+
apiSecret: 'apiSecret',
60+
};
61+
const { value } = schema.validate(options);
62+
63+
expect(value).toEqual({
64+
...options,
65+
resourceType: 'image',
66+
maxResults: 10,
67+
resultsPerPage: 10,
68+
tags: false,
69+
type: 'all',
70+
});
71+
});
72+
});

0 commit comments

Comments
 (0)