Skip to content

Commit 0b38edd

Browse files
authored
Add tests (#41)
* refactor: move index.js to src/index.js * Add basic tests * fix: check for redirect.to which might be absent in special cases * chore: add github workflow to test on PR
1 parent 6fd9afe commit 0b38edd

File tree

6 files changed

+253
-5
lines changed

6 files changed

+253
-5
lines changed

.github/workflows/test.yml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
name: Plugin Tests
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
8+
jobs:
9+
build:
10+
runs-on: ubuntu-latest
11+
12+
strategy:
13+
matrix:
14+
node-version: [10.x, 12.x, 14.x]
15+
16+
steps:
17+
- uses: actions/checkout@v2
18+
- name: Use Node.js ${{ matrix.node-version }}
19+
uses: actions/setup-node@v1
20+
with:
21+
node-version: ${{ matrix.node-version }}
22+
- run: npm install
23+
- run: npm test

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
**/**/node_modules
2-
yarn.lock
2+
yarn.lock
3+
package-lock.json
4+
coverage

__mocks__/netlify-lambda/lib/build.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module.exports = {
2+
run: jest.fn()
3+
};

package.json

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
{
22
"name": "netlify-plugin-nimbella",
33
"version": "1.7.0",
4-
"main": "index.js",
4+
"main": "src/index.js",
55
"description": "Nimbella add-on for Netlify to extends Netlify Sites with serverless functions and stateful APIs using Nimbella Cloud.",
66
"scripts": {
77
"setup": "yarn install",
8-
"test": "xo"
8+
"test": "xo && jest --coverage"
99
},
1010
"repository": {
1111
"type": "git",
@@ -34,7 +34,11 @@
3434
},
3535
"xo": {
3636
"space": true,
37-
"prettier": true
37+
"prettier": true,
38+
"envs": [
39+
"node",
40+
"jest"
41+
]
3842
},
3943
"engines": {
4044
"node": ">=12.0.0"
@@ -46,10 +50,18 @@
4650
},
4751
"files": [
4852
"manifest.yml",
49-
"index.js"
53+
"src"
5054
],
55+
"jest": {
56+
"testMatch": [
57+
"**/test/**/*.js"
58+
],
59+
"verbose": true
60+
},
5161
"devDependencies": {
5262
"husky": "^4.3.0",
63+
"jest": "^26.5.3",
64+
"mock-fs": "^4.13.0",
5365
"xo": "^0.33.0"
5466
}
5567
}

index.js renamed to src/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ module.exports = {
193193
for (const redirect of redirects) {
194194
if (
195195
redirect.status === 200 &&
196+
redirect.to &&
196197
redirect.to.startsWith('/.netlify/functions/')
197198
) {
198199
const redirectPath = redirect.to.split('/.netlify/functions/')[1];

test/index.js

Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
const path = require('path');
2+
3+
const mockFs = require('mock-fs');
4+
const build = require('netlify-lambda/lib/build');
5+
6+
const plugin = require('../src');
7+
8+
const utils = {
9+
cache: {
10+
restore: jest.fn(),
11+
save: jest.fn(),
12+
has: jest.fn()
13+
},
14+
run: {
15+
command: jest.fn()
16+
},
17+
build: {
18+
failBuild: jest.fn()
19+
}
20+
};
21+
jest.mock('netlify-lambda/lib/build');
22+
console.log = jest.fn();
23+
24+
afterEach(() => {
25+
delete require.cache[require.resolve('../src')];
26+
utils.build.failBuild.mockReset();
27+
utils.run.command.mockReset();
28+
utils.cache.has.mockReset();
29+
utils.cache.restore.mockReset();
30+
utils.cache.save.mockReset();
31+
build.run.mockReset();
32+
console.log.mockReset();
33+
});
34+
35+
describe('preBuild()', () => {
36+
test('show token not available message when login token not set', async () => {
37+
// Prepare
38+
process.env.NIMBELLA_LOGIN_TOKEN = '';
39+
utils.cache.has.mockResolvedValue(false);
40+
41+
await plugin.onPreBuild({
42+
utils,
43+
constants: {},
44+
inputs: {}
45+
});
46+
47+
expect(utils.cache.has.mock.calls.length).toBe(1);
48+
expect(utils.build.failBuild.mock.calls[0][0]).toEqual(
49+
'Nimbella login token is not available. Please run `netlify addons:create nimbella` at the base of your local project directory linked to your Netlify site.'
50+
);
51+
});
52+
53+
test('Show the current namespace if already logged in', async () => {
54+
// Prepare
55+
process.env.NIMBELLA_LOGIN_TOKEN = 'somevalue';
56+
utils.run.command.mockReturnValue({
57+
stdout: 'namespace'
58+
});
59+
const mockFiles = {
60+
[path.join(require('os').homedir(), '.nimbella')]: {}
61+
};
62+
63+
mockFs(mockFiles);
64+
await plugin.onPreBuild({
65+
utils,
66+
constants: {},
67+
inputs: {}
68+
});
69+
mockFs.restore();
70+
71+
expect(utils.cache.restore.mock.calls.length).toBe(1);
72+
expect(utils.run.command.mock.calls[0][0]).toEqual(`nim auth current`);
73+
expect(console.log.mock.calls[0][0]).toEqual(
74+
'Using the following namespace: namespace'
75+
);
76+
});
77+
});
78+
79+
describe('onBuild()', () => {
80+
test('should build functions if functions input is set in config ', async () => {
81+
process.env.NIMBELLA_LOGIN_TOKEN = 'somevalue';
82+
83+
mockFs({
84+
functions: {},
85+
'netlify.toml': ''
86+
});
87+
await plugin.onPreBuild({
88+
utils,
89+
constants: {CONFIG_PATH: './netlify.toml'},
90+
inputs: {functions: 'functions'}
91+
});
92+
await plugin.onBuild({
93+
utils,
94+
inputs: {functions: 'functions'}
95+
});
96+
mockFs.restore();
97+
98+
expect(build.run.mock.calls[0][1]).toEqual('functions');
99+
});
100+
101+
test('should not build functions if set functions directory is not present', async () => {
102+
mockFs({
103+
packages: {},
104+
'netlify.toml': ''
105+
});
106+
await plugin.onPreBuild({
107+
utils,
108+
constants: {CONFIG_PATH: './netlify.toml'},
109+
inputs: {functions: 'abcd'}
110+
});
111+
await plugin.onBuild({
112+
utils,
113+
inputs: {functions: 'abcd'}
114+
});
115+
mockFs.restore();
116+
117+
expect(build.run.mock.calls.length).toBe(0);
118+
});
119+
});
120+
121+
describe('onPostBuild()', () => {
122+
test('should skip deployment if the context is not production', async () => {
123+
process.env.NIMBELLA_LOGIN_TOKEN = 'somevalue';
124+
process.env.CONTEXT = 'dev';
125+
utils.run.command.mockReturnValue({
126+
stdout: 'namespace'
127+
});
128+
const pluginInputs = {
129+
utils,
130+
constants: {CONFIG_PATH: './netlify.toml', PUBLISH_DIR: ''},
131+
inputs: {
132+
path: '',
133+
functions: ''
134+
}
135+
};
136+
137+
mockFs({});
138+
await plugin.onPostBuild(pluginInputs);
139+
mockFs.restore();
140+
141+
expect(console.log.mock.calls[0][0]).toEqual(
142+
`Skipping the deployment to Nimbella as the context (${process.env.CONTEXT}) is not production.`
143+
);
144+
});
145+
146+
test("should run nim project deploy if 'packages' directory exists", async () => {
147+
process.env.NIMBELLA_LOGIN_TOKEN = 'somevalue';
148+
process.env.CONTEXT = 'production';
149+
utils.run.command.mockReturnValue({
150+
stdout: 'namespace'
151+
});
152+
const pluginInputs = {
153+
utils,
154+
constants: {CONFIG_PATH: './netlify.toml', PUBLISH_DIR: ''},
155+
inputs: {
156+
path: '',
157+
functions: ''
158+
}
159+
};
160+
161+
mockFs({
162+
packages: {}
163+
});
164+
await plugin.onPreBuild(pluginInputs);
165+
await plugin.onPostBuild(pluginInputs);
166+
mockFs.restore();
167+
168+
expect(utils.run.command.mock.calls[2][0]).toEqual(
169+
`nim project deploy . --exclude=web`
170+
);
171+
});
172+
173+
test('should rewrite existing redirects to .netlify/functions/ in netlify.toml if functions are used', async () => {
174+
process.env.NIMBELLA_LOGIN_TOKEN = 'somevalue';
175+
process.env.CONTEXT = 'production';
176+
utils.run.command.mockReturnValue({
177+
stdout: 'namespace'
178+
});
179+
const pluginInputs = {
180+
utils,
181+
constants: {CONFIG_PATH: 'netlify.toml', PUBLISH_DIR: ''},
182+
inputs: {
183+
path: '',
184+
functions: 'some-dir'
185+
}
186+
};
187+
188+
mockFs({
189+
'netlify.toml': `
190+
[[redirects]]
191+
from = "/*"
192+
to = "/index.html"
193+
status = 200
194+
`,
195+
'some-dir': {
196+
'create.js': '',
197+
'update.js': ''
198+
}
199+
});
200+
await plugin.onPreBuild(pluginInputs);
201+
await plugin.onPostBuild(pluginInputs);
202+
mockFs.restore();
203+
expect(console.log.mock.calls[1][0]).toEqual(
204+
"Found redirect rules in netlify.toml. We will rewrite rules that redirect (200 rewrites) to '/.netlify/functions/*'."
205+
);
206+
});
207+
});

0 commit comments

Comments
 (0)