UNPKG

9.84 kBJavaScriptView Raw
1/*!
2Kettle Data Source Tests
3
4Copyright 2017-2018 OCAD University
5Copyright 2012-2015 Raising the Floor - International
6
7Licensed under the New BSD license. You may not use this file except in
8compliance with this License.
9
10You may obtain a copy of the License at
11https://github.com/fluid-project/kettle/blob/master/LICENSE.txt
12*/
13
14"use strict";
15
16var fluid = require("infusion"),
17 kettle = require("../kettle.js"),
18 fs = require("fs"),
19 querystring = require("querystring"),
20 http = require("http"),
21 https = require("https"),
22 jqUnit = fluid.require("node-jqunit", require, "jqUnit");
23
24require("./shared/DataSourceTestUtils.js");
25
26kettle.tests.dataSource.ensureDirectoryEmpty("%kettle/tests/data/writeable");
27
28/** KETTLE-34 options resolution and merging test **/
29
30fluid.defaults("kettle.tests.KETTLE34dataSource", {
31 gradeNames: "kettle.dataSource.URL",
32 url: "https://user:password@thing.available:997/path",
33 headers: {
34 "x-custom-header": "x-custom-value"
35 },
36 censorRequestOptionsLog: {
37 auth: false
38 }
39});
40
41fluid.defaults("kettle.tests.KETTLE34dataSource2", {
42 gradeNames: "kettle.dataSource.URL",
43 url: "http://127.0.0.1/device",
44 port: 998
45});
46
47
48kettle.tests.dataSource.resolutionTests = [ {
49 gradeName: "kettle.tests.KETTLE34dataSource",
50 expectedOptions: {
51 protocol: "https:",
52 port: 999,
53 auth: "user:password",
54 path: "/path",
55 method: "GET",
56 host: "thing.available:997", // appears to be a parsing fault in url module
57 family: 4,
58 headers: {
59 "x-custom-header": "x-custom-value",
60 "x-custom-header2": "x-custom-value2"
61 }
62 },
63 creatorArgs: {
64 port: 998,
65 family: 4
66 },
67 directOptions: {
68 headers: {
69 "x-custom-header2": "x-custom-value2"
70 },
71 port: 999
72 }
73}, {
74 gradeName: "kettle.tests.KETTLE34dataSource2",
75 expectedOptions: {
76 protocol: "http:",
77 port: 998,
78 path: "/device",
79 host: "127.0.0.1"
80 }
81}
82];
83
84kettle.tests.capturedHttpOptions = {};
85
86kettle.tests.withMockHttp = function (toapply) {
87 return function () {
88 var httpRequest = http.request;
89 var httpsRequest = https.request;
90 kettle.tests.capturedHttpOptions = {};
91 http.request = https.request = function (requestOptions) {
92 kettle.tests.capturedHttpOptions = requestOptions;
93 return {
94 on: fluid.identity,
95 end: fluid.identity
96 };
97 };
98 try {
99 toapply();
100 } finally {
101 http.request = httpRequest;
102 https.request = httpsRequest;
103 }
104 };
105};
106
107kettle.tests.dataSource.resolutionTest = function (fixture) {
108 jqUnit.test("KETTLE-34 request option resolution test", kettle.tests.withMockHttp(function () {
109 var dataSource = fluid.invokeGlobalFunction(fixture.gradeName, [fixture.creatorArgs]);
110 dataSource.get(null, fixture.directOptions);
111 jqUnit.assertLeftHand("Resolved expected requestOptions", fixture.expectedOptions, kettle.tests.capturedHttpOptions);
112 }));
113};
114
115fluid.each(kettle.tests.dataSource.resolutionTests, function (fixture) {
116 kettle.tests.dataSource.resolutionTest(fixture);
117});
118
119/** KETTLE-73 censoring sensitive options test **/
120
121fluid.defaults("kettle.tests.KETTLE73dataSource", {
122 gradeNames: "kettle.dataSource.URL"
123});
124
125kettle.tests.censoringTests = [{
126 url: "https://secret-user:secret-password@thing.available:997/path",
127 headers: {
128 Authorization: "secret-authorization",
129 "X-unrelated-header": "998"
130 },
131 shouldNotApper: "secret",
132 shouldAppear: ["997", "998"]
133}, {
134 url: "https://secret-user:secret-%25-password@thing.available:997/path",
135 headers: {
136 Authorization: "secret-%25-authorization",
137 "X-unrelated-header": "998"
138 },
139 shouldNotAppear: "secret",
140 shouldAppear: ["997", "998"]
141}];
142
143jqUnit.test("KETTLE-73 censoring test", kettle.tests.withMockHttp(function () {
144 var memoryLog;
145 var memoryLogger = function (args) {
146 memoryLog.push(JSON.stringify(args.slice(1)));
147 };
148 fluid.loggingEvent.addListener(memoryLogger, "memoryLogger", "before:log");
149 kettle.tests.censoringTests.forEach(function (fixture) {
150 memoryLog = [];
151 var that = kettle.tests.KETTLE73dataSource({url: fixture.url});
152 that.get(null, {headers: fixture.headers});
153 jqUnit.assertTrue("Secret information should not have been logged", memoryLog[0].indexOf(fixture.shouldNotAppear) === -1);
154 fixture.shouldAppear.forEach(function (shouldAppear) {
155 jqUnit.assertTrue("URL port and header should have been logged", memoryLog[0].indexOf(shouldAppear) !== -1);
156 });
157 });
158 fluid.loggingEvent.removeListener("memoryLogger");
159}));
160
161/** KETTLE-38 writeable grade resolution test **/
162
163fluid.defaults("kettle.tests.KETTLE38base", {
164 gradeNames: "kettle.dataSource.URL",
165 writable: true
166});
167
168fluid.defaults("kettle.tests.KETTLE38derived", {
169 gradeNames: "kettle.tests.KETTLE38base"
170});
171
172jqUnit.test("KETTLE-38 derived writable dataSource test", function () {
173 var dataSource = kettle.tests.KETTLE38derived();
174 jqUnit.assertValue("Resolved writable grade via base grade", dataSource.set);
175});
176
177/** Form encoding test **/
178
179kettle.tests.formencData = {
180 "text1": "text default",
181 "text2": "aωb"
182};
183
184fluid.defaults("kettle.tests.formencSource", {
185 gradeNames: "kettle.dataSource.file.moduleTerms",
186 path: "%kettle/tests/data/formenc.txt",
187 components: {
188 encoding: {
189 type: "kettle.dataSource.encoding.formenc"
190 }
191 }
192});
193
194jqUnit.asyncTest("Reading file in formenc encoding", function () {
195 var that = kettle.tests.formencSource();
196 jqUnit.expect(1);
197 that.get().then(function (result) {
198 jqUnit.assertDeepEq("Received decoded result", kettle.tests.formencData, result);
199 jqUnit.start();
200 }, function (err) {
201 jqUnit.fail("Got error " + JSON.stringify(err));
202 });
203});
204
205fluid.defaults("kettle.tests.formencSourceWrite", {
206 gradeNames: "kettle.dataSource.file.moduleTerms",
207 path: "%kettle/tests/data/writeable/formenc.txt",
208 writable: true,
209 components: {
210 encoding: {
211 type: "kettle.dataSource.encoding.formenc"
212 }
213 }
214});
215
216jqUnit.asyncTest("Writing file in formenc encoding", function () {
217 var that = kettle.tests.formencSourceWrite();
218 jqUnit.expect(1);
219 that.set(null, kettle.tests.formencData).then(function () {
220 var written = fs.readFileSync(fluid.module.resolvePath("%kettle/tests/data/writeable/formenc.txt"), "utf8");
221 var decoded = querystring.parse(written);
222 jqUnit.assertDeepEq("Written decoded result", kettle.tests.formencData, decoded);
223 jqUnit.start();
224 }, function (err) {
225 jqUnit.fail("Got error " + JSON.stringify(err));
226 });
227});
228
229
230// Basic initialisation tests
231
232kettle.tests.dataSource.testInit = function (dataSource) {
233 jqUnit.expect(4);
234 jqUnit.assertValue("Data source is initialized", dataSource);
235 jqUnit.assertValue("Data source should have a get method", dataSource.get);
236 jqUnit.assertUndefined("Data source should not have a set method by default", dataSource.set);
237 jqUnit.assertDeepEq("Data source should have a termMap", {}, dataSource.options.termMap);
238};
239
240
241fluid.defaults("kettle.tests.dataSource.initTester", {
242 gradeNames: "fluid.component",
243 components: {
244 urlDataSource: {
245 type: "kettle.dataSource.URL"
246 },
247 couchDBDataSource: {
248 type: "kettle.dataSource.URL",
249 options: {
250 gradeNames: "kettle.dataSource.CouchDB"
251 }
252 }
253 }
254});
255
256jqUnit.test("DataSource basic init tests", function () {
257 var initTester = kettle.tests.dataSource.initTester();
258 kettle.tests.dataSource.testInit(initTester.urlDataSource);
259 kettle.tests.dataSource.testInit(initTester.couchDBDataSource);
260});
261
262
263fluid.defaults("kettle.tests.dataSource.fileWithoutPath", {
264 gradeNames: "kettle.dataSource.file"
265});
266
267jqUnit.test("DataSource without path", function () {
268 jqUnit.expectFrameworkDiagnostic("DataSource without path", function () {
269 var source = kettle.tests.dataSource.fileWithoutPath();
270 source.get();
271 }, ["without an option", "path"]);
272});
273
274// Attached URL resolver tests
275
276kettle.tests.testUrlResolver = function (gradeName) {
277 var dataSource = fluid.invokeGlobalFunction(gradeName);
278 var resolved = dataSource.resolveUrl(dataSource.options.url, dataSource.options.termMap, dataSource.options.directModel);
279 jqUnit.assertEquals(dataSource.options.message, resolved, dataSource.options.expected, resolved);
280};
281
282fluid.defaults("kettle.tests.dataSource.dynamicURL", {
283 gradeNames: "kettle.dataSource.URL",
284 url: "http://%expand/test.json",
285 termMap: {
286 expand: "%expand"
287 },
288 message: "URL resolver with URI escaping",
289 directModel: {
290 expand: "test with space"
291 },
292 expected: "http://test%20with%20space/test.json"
293});
294
295fluid.defaults("kettle.tests.dataSource.unescapedUrl", {
296 gradeNames: "kettle.dataSource.URL",
297 url: "http://%expand/test.json",
298 termMap: {
299 expand: "noencode:%expand"
300 },
301 message: "URL resolver with URI escaping",
302 directModel: {
303 expand: "test/with/slash"
304 },
305 expected: "http://test/with/slash/test.json"
306});
307
308jqUnit.test("Attached URLResolver tests", function () {
309 kettle.tests.testUrlResolver("kettle.tests.dataSource.dynamicURL");
310 kettle.tests.testUrlResolver("kettle.tests.dataSource.unescapedUrl");
311});
312
313jqUnit.onAllTestsDone.addListener(function () {
314 kettle.tests.dataSource.ensureDirectoryEmpty("%kettle/tests/data/writeable");
315});