UNPKG

8.12 kBJavaScriptView Raw
1/*eslint no-magic-numbers: "off"*/
2/*eslint no-invalid-this: "off"*/
3const _ = require('lodash');
4const expect = require('chai').expect;
5const Promise = require('bluebird');
6const TestConfig = require('../config');
7const Utils = require('../utils');
8const Filters = require('../../app/services/filters');
9const ObjectId = require('../../app/models/objectId');
10const createRedisClient = require('../../config/redis');
11const config = require('../../config/index');
12
13const log = config.log;
14
15Promise.longStackTraces();
16Promise.onPossiblyUnhandledRejection((error) => log.error('Likely error: ', error.stack));
17
18const ns = 'namespace';
19const id = 'id';
20const topLevelArguments = {
21 first: 'this thing',
22 second: 'other thing'
23};
24const specificArguments = {
25 second: 'second thing',
26 third: 'last thing'
27};
28const validateFilter = (filter) => expect(_.isFunction(filter.predicate)).is.true;
29
30describe('filters service', function () {
31 this.timeout(5000);
32
33 let filters = null;
34 let redis = null;
35 let objectId = null;
36 let utils = null;
37
38 before((done) => {
39 redis = createRedisClient(TestConfig.redis.host, TestConfig.redis.port);
40 filters = new Filters(redis);
41 utils = new Utils();
42 done();
43 });
44
45 after((done) => {
46 redis.flushdb().finally(() => done());
47 });
48
49 beforeEach((done) => {
50 objectId = new ObjectId({namespace: ns, id});
51 redis.flushdb().finally(() => done());
52 });
53
54 it('invalid id', (done) => {
55 objectId.id = '~badId';
56 filters.add(objectId, 'dummySrc')
57 .then(() => done('fail'))
58 .catch((e) => expect(e.message).equals("Id must be string of 1-40 alphanumeric characters, given '~badId'"))
59 .then(() => done());
60 }
61 );
62
63 it('invalid src type', (done) => {
64 filters.add(objectId, {})
65 .then(() => done('fail'))
66 .catch((e) => expect(e.message).equals('filterSrc must be string'))
67 .then(() => done());
68 });
69
70 it('invalid javascript', (done) => {
71 filters.add(objectId, utils.loadFile(`${__dirname}/invalidFilters/notAJsFile`))
72 .then(() => done('fail'))
73 .catch((e) => expect(e.message).equals("Unable to load external module due to 'SyntaxError - Unexpected identifier'"))
74 .then(() => done());
75 });
76
77 it('filter missing type', (done) => {
78 filters.add(objectId, utils.loadFile(`${__dirname}/invalidFilters/noType.js`))
79 .then(() => done('fail'))
80 .catch((e) => expect(e.message).equals('Filter type string not provided'))
81 .then(() => done());
82 });
83
84 it('filter invalid type', (done) => {
85 filters.add(objectId, utils.loadFile(`${__dirname}/invalidFilters/invalidType.js`))
86 .then(() => done('fail'))
87 .catch((e) => expect(e.message).equals(`Filter type 'wrong' not one of: [${Filters.TYPES}]`))
88 .then(() => done());
89 });
90
91 it('filter missing predicate', (done) => {
92 filters.add(objectId, utils.loadFile(`${__dirname}/invalidFilters/noPredicate.js`))
93 .then(() => done('fail'))
94 .catch((e) => expect(e.message).equals('Filter predicate() not provided'))
95 .then(() => done());
96 });
97
98 it('get ids in empty namespace', (done) => {
99 filters.getIds(ns)
100 .then((ids) => expect(ids).to.be.empty)
101 .then(() => done());
102 });
103
104 it('basic crud', (done) => {
105 filters.add(objectId, utils.loadFile(`${__dirname}/validFilters/index.js`))
106 .then(() => filters.exists(objectId))
107 .then((exists) => expect(exists).to.be.equals(1))
108 .then(() => filters.getIds(ns)
109 .then((ids) => {
110 expect(ids).to.have.length(1);
111 expect(ids[0]).to.be.equals('id');
112 })
113 )
114 .then(() => filters.remove(objectId))
115 .then(() => filters.exists(objectId))
116 .then((exists) => expect(exists).to.be.equals(0))
117 .then(() => filters.getIds(ns))
118 .then((ids) => expect(ids).to.be.empty)
119 .then(() => done());
120 });
121
122 it('add twice', (done) => {
123 filters.add(objectId, utils.loadFile(`${__dirname}/validFilters/index.js`))
124 .then(() => filters.exists(objectId))
125 .then((exists) => expect(exists).to.be.equals(1))
126 .then(() => filters.add(objectId, utils.loadFile(`${__dirname}/validFilters/index.js`)))
127 .catch((e) => expect(e.message).to.be.equals('Filter \'namespace/id\' exists, delete first.'))
128 .then(() => done());
129 });
130
131 it('load a specific filter with top-level args', (done) => {
132 filters.add(objectId, utils.loadFile(`${__dirname}/validFilters/index.js`))
133 .then(() => filters.load(ns, {
134 actions: [
135 {id}
136 ],
137 arguments: topLevelArguments
138 }))
139 .then((loadedFilters) => {
140 expect(_.size(loadedFilters)).to.be.equals(1);
141 expect(loadedFilters['index']).to.have.length(1);
142
143 const data = loadedFilters['index'][0];
144 expect(data.type).to.be.equals('index');
145 expect(data.arguments).to.be.equals(topLevelArguments);
146 validateFilter(data);
147 done();
148 })
149 .catch(done);
150 });
151
152 it('load a specific filter with arg overrides', (done) => {
153 filters.add(objectId, utils.loadFile(`${__dirname}/validFilters/index.js`))
154 .then(() => filters.load(ns, {
155 actions: [
156 {id, arguments: specificArguments}
157 ],
158 arguments: topLevelArguments
159 }))
160 .then((loadedFilters) => {
161 expect(_.size(loadedFilters)).to.be.equals(1);
162 expect(loadedFilters['index']).to.have.length(1);
163
164 const data = loadedFilters['index'][0];
165 expect(data.type).to.be.equals('index');
166 expect(data.arguments).to.be.equals(specificArguments);
167 validateFilter(data);
168 done();
169 })
170 .catch(done);
171 });
172
173 it('load a multiple filters in different namespaces', (done) => {
174 const objectId1 = new ObjectId({namespace: 'task', id});
175 const objectId2 = new ObjectId({namespace: 'global', id});
176 const objectId3 = new ObjectId({namespace: 'othernamespace', id});
177 const objectId4 = new ObjectId({namespace: 'othernamespace', id: 'other'});
178
179 filters.add(objectId1, utils.loadFile(`${__dirname}/validFilters/index.js`))
180 .then(() => filters.add(objectId2, utils.loadFile(`${__dirname}/validFilters/type.js`)))
181 .then(() => filters.add(objectId3, utils.loadFile(`${__dirname}/validFilters/typeWithArgs.js`)))
182 .then(() => filters.add(objectId4, utils.loadFile(`${__dirname}/validFilters/index.js`)))
183 .then(() => filters.load('task', {
184 actions: [
185 {
186 namespace: objectId3.namespace,
187 id: objectId3.id,
188 arguments: specificArguments
189 },
190 {
191 namespace: objectId2.namespace,
192 id: objectId2.id
193 },
194 {
195 id: objectId1.id,
196 arguments: specificArguments
197 },
198 {
199 namespace: objectId4.namespace,
200 id: objectId4.id
201 }
202 ],
203 arguments: topLevelArguments
204 }))
205 .then((loadedFilters) => {
206 expect(_.size(loadedFilters)).to.be.equals(2);
207 expect(loadedFilters['index']).to.have.length(2);
208 expect(loadedFilters['type']).to.have.length(2);
209
210 const index1 = loadedFilters['index'][0];
211 expect(index1.type).to.be.equals('index');
212 expect(index1.arguments).to.be.equals(specificArguments);
213 validateFilter(index1);
214
215 const index2 = loadedFilters['index'][0];
216 expect(index2.type).to.be.equals('index');
217 expect(index2.arguments).to.be.equals(specificArguments);
218 validateFilter(index2);
219
220 const type1 = loadedFilters['type'][0];
221 expect(type1.type).to.be.equals('type');
222 expect(type1.arguments).to.be.equals(specificArguments);
223 validateFilter(type1);
224
225 const type2 = loadedFilters['type'][1];
226 expect(type2.type).to.be.equals('type');
227 expect(type2.arguments).to.be.equals(topLevelArguments);
228 validateFilter(type2);
229 })
230 .then(() => done())
231 .catch(done);
232 });
233});