1 |
|
2 |
|
3 | const _ = require('lodash');
|
4 | const expect = require('chai').expect;
|
5 | const Promise = require('bluebird');
|
6 | const TestConfig = require('../config');
|
7 | const Utils = require('../utils');
|
8 | const Filters = require('../../app/services/filters');
|
9 | const ObjectId = require('../../app/models/objectId');
|
10 | const createRedisClient = require('../../config/redis');
|
11 | const config = require('../../config/index');
|
12 |
|
13 | const log = config.log;
|
14 |
|
15 | Promise.longStackTraces();
|
16 | Promise.onPossiblyUnhandledRejection((error) => log.error('Likely error: ', error.stack));
|
17 |
|
18 | const ns = 'namespace';
|
19 | const id = 'id';
|
20 | const topLevelArguments = {
|
21 | first: 'this thing',
|
22 | second: 'other thing'
|
23 | };
|
24 | const specificArguments = {
|
25 | second: 'second thing',
|
26 | third: 'last thing'
|
27 | };
|
28 | const validateFilter = (filter) => expect(_.isFunction(filter.predicate)).is.true;
|
29 |
|
30 | describe('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 | });
|