@xapi-js/adaptor-nestjs 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +83 -0
- package/dist/index.d.cts +45 -0
- package/dist/index.d.ts +45 -0
- package/dist/index.js +56 -0
- package/package.json +6 -3
- package/coverage/base.css +0 -224
- package/coverage/block-navigation.js +0 -87
- package/coverage/clover.xml +0 -49
- package/coverage/coverage-final.json +0 -3
- package/coverage/favicon.png +0 -0
- package/coverage/index.html +0 -131
- package/coverage/prettify.css +0 -1
- package/coverage/prettify.js +0 -2
- package/coverage/sort-arrow-sprite.png +0 -0
- package/coverage/sorter.js +0 -196
- package/coverage/xapi-request-interceptor.ts.html +0 -133
- package/coverage/xapi-response-interceptor.ts.html +0 -169
- package/src/xapi-request-interceptor.ts +0 -31
- package/src/xapi-response-interceptor.ts +0 -43
- package/test/xapi-request-interceptor.test.ts +0 -115
- package/test/xapi-response-interceptor.test.ts +0 -113
- package/vitest.config.ts +0 -16
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
<!doctype html>
|
|
3
|
-
<html lang="en">
|
|
4
|
-
|
|
5
|
-
<head>
|
|
6
|
-
<title>Code coverage report for xapi-response-interceptor.ts</title>
|
|
7
|
-
<meta charset="utf-8" />
|
|
8
|
-
<link rel="stylesheet" href="prettify.css" />
|
|
9
|
-
<link rel="stylesheet" href="base.css" />
|
|
10
|
-
<link rel="shortcut icon" type="image/x-icon" href="favicon.png" />
|
|
11
|
-
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
12
|
-
<style type='text/css'>
|
|
13
|
-
.coverage-summary .sorter {
|
|
14
|
-
background-image: url(sort-arrow-sprite.png);
|
|
15
|
-
}
|
|
16
|
-
</style>
|
|
17
|
-
</head>
|
|
18
|
-
|
|
19
|
-
<body>
|
|
20
|
-
<div class='wrapper'>
|
|
21
|
-
<div class='pad1'>
|
|
22
|
-
<h1><a href="index.html">All files</a> xapi-response-interceptor.ts</h1>
|
|
23
|
-
<div class='clearfix'>
|
|
24
|
-
|
|
25
|
-
<div class='fl pad1y space-right2'>
|
|
26
|
-
<span class="strong">100% </span>
|
|
27
|
-
<span class="quiet">Statements</span>
|
|
28
|
-
<span class='fraction'>24/24</span>
|
|
29
|
-
</div>
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
<div class='fl pad1y space-right2'>
|
|
33
|
-
<span class="strong">100% </span>
|
|
34
|
-
<span class="quiet">Branches</span>
|
|
35
|
-
<span class='fraction'>6/6</span>
|
|
36
|
-
</div>
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
<div class='fl pad1y space-right2'>
|
|
40
|
-
<span class="strong">100% </span>
|
|
41
|
-
<span class="quiet">Functions</span>
|
|
42
|
-
<span class='fraction'>2/2</span>
|
|
43
|
-
</div>
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
<div class='fl pad1y space-right2'>
|
|
47
|
-
<span class="strong">100% </span>
|
|
48
|
-
<span class="quiet">Lines</span>
|
|
49
|
-
<span class='fraction'>24/24</span>
|
|
50
|
-
</div>
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
</div>
|
|
54
|
-
<p class="quiet">
|
|
55
|
-
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
|
|
56
|
-
</p>
|
|
57
|
-
<template id="filterTemplate">
|
|
58
|
-
<div class="quiet">
|
|
59
|
-
Filter:
|
|
60
|
-
<input type="search" id="fileSearch">
|
|
61
|
-
</div>
|
|
62
|
-
</template>
|
|
63
|
-
</div>
|
|
64
|
-
<div class='status-line high'></div>
|
|
65
|
-
<pre><table class="coverage">
|
|
66
|
-
<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
|
|
67
|
-
<a name='L2'></a><a href='#L2'>2</a>
|
|
68
|
-
<a name='L3'></a><a href='#L3'>3</a>
|
|
69
|
-
<a name='L4'></a><a href='#L4'>4</a>
|
|
70
|
-
<a name='L5'></a><a href='#L5'>5</a>
|
|
71
|
-
<a name='L6'></a><a href='#L6'>6</a>
|
|
72
|
-
<a name='L7'></a><a href='#L7'>7</a>
|
|
73
|
-
<a name='L8'></a><a href='#L8'>8</a>
|
|
74
|
-
<a name='L9'></a><a href='#L9'>9</a>
|
|
75
|
-
<a name='L10'></a><a href='#L10'>10</a>
|
|
76
|
-
<a name='L11'></a><a href='#L11'>11</a>
|
|
77
|
-
<a name='L12'></a><a href='#L12'>12</a>
|
|
78
|
-
<a name='L13'></a><a href='#L13'>13</a>
|
|
79
|
-
<a name='L14'></a><a href='#L14'>14</a>
|
|
80
|
-
<a name='L15'></a><a href='#L15'>15</a>
|
|
81
|
-
<a name='L16'></a><a href='#L16'>16</a>
|
|
82
|
-
<a name='L17'></a><a href='#L17'>17</a>
|
|
83
|
-
<a name='L18'></a><a href='#L18'>18</a>
|
|
84
|
-
<a name='L19'></a><a href='#L19'>19</a>
|
|
85
|
-
<a name='L20'></a><a href='#L20'>20</a>
|
|
86
|
-
<a name='L21'></a><a href='#L21'>21</a>
|
|
87
|
-
<a name='L22'></a><a href='#L22'>22</a>
|
|
88
|
-
<a name='L23'></a><a href='#L23'>23</a>
|
|
89
|
-
<a name='L24'></a><a href='#L24'>24</a>
|
|
90
|
-
<a name='L25'></a><a href='#L25'>25</a>
|
|
91
|
-
<a name='L26'></a><a href='#L26'>26</a>
|
|
92
|
-
<a name='L27'></a><a href='#L27'>27</a>
|
|
93
|
-
<a name='L28'></a><a href='#L28'>28</a>
|
|
94
|
-
<a name='L29'></a><a href='#L29'>29</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">1x</span>
|
|
95
|
-
<span class="cline-any cline-neutral"> </span>
|
|
96
|
-
<span class="cline-any cline-neutral"> </span>
|
|
97
|
-
<span class="cline-any cline-neutral"> </span>
|
|
98
|
-
<span class="cline-any cline-yes">1x</span>
|
|
99
|
-
<span class="cline-any cline-yes">1x</span>
|
|
100
|
-
<span class="cline-any cline-yes">4x</span>
|
|
101
|
-
<span class="cline-any cline-yes">1x</span>
|
|
102
|
-
<span class="cline-any cline-yes">3x</span>
|
|
103
|
-
<span class="cline-any cline-yes">3x</span>
|
|
104
|
-
<span class="cline-any cline-yes">3x</span>
|
|
105
|
-
<span class="cline-any cline-yes">3x</span>
|
|
106
|
-
<span class="cline-any cline-yes">2x</span>
|
|
107
|
-
<span class="cline-any cline-neutral"> </span>
|
|
108
|
-
<span class="cline-any cline-yes">2x</span>
|
|
109
|
-
<span class="cline-any cline-yes">1x</span>
|
|
110
|
-
<span class="cline-any cline-yes">1x</span>
|
|
111
|
-
<span class="cline-any cline-yes">1x</span>
|
|
112
|
-
<span class="cline-any cline-yes">1x</span>
|
|
113
|
-
<span class="cline-any cline-yes">1x</span>
|
|
114
|
-
<span class="cline-any cline-yes">2x</span>
|
|
115
|
-
<span class="cline-any cline-yes">1x</span>
|
|
116
|
-
<span class="cline-any cline-yes">1x</span>
|
|
117
|
-
<span class="cline-any cline-yes">1x</span>
|
|
118
|
-
<span class="cline-any cline-yes">3x</span>
|
|
119
|
-
<span class="cline-any cline-yes">3x</span>
|
|
120
|
-
<span class="cline-any cline-yes">3x</span>
|
|
121
|
-
<span class="cline-any cline-yes">1x</span>
|
|
122
|
-
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">import { CallHandler, ExecutionContext, Injectable, Logger, NestInterceptor } from '@nestjs/common';
|
|
123
|
-
import { XapiRoot, writeString } from '@xapi-js/core';
|
|
124
|
-
import { Observable, map } from 'rxjs';
|
|
125
|
-
|
|
126
|
-
@Injectable()
|
|
127
|
-
export class XapiResponseInterceptor implements NestInterceptor<XapiRoot, Promise<string>> {
|
|
128
|
-
private readonly logger: Logger = new Logger(XapiResponseInterceptor.name);
|
|
129
|
-
intercept(context: ExecutionContext, next: CallHandler): Observable<Promise<string>> {
|
|
130
|
-
this.logger.debug(`XapiResponseInterceptor Intercepting response`);
|
|
131
|
-
return next.handle().pipe(
|
|
132
|
-
map(async (value) => {
|
|
133
|
-
if (value instanceof XapiRoot) {
|
|
134
|
-
try {
|
|
135
|
-
// Serialize XapiRoot output to XML string
|
|
136
|
-
const xmlOutput = await writeString(value as XapiRoot);
|
|
137
|
-
return xmlOutput!!;
|
|
138
|
-
} catch (error) {
|
|
139
|
-
this.logger.error(`Failed to serialize XapiRoot to XML string: ${error.message}`);
|
|
140
|
-
throw error; // Re-throw the original error
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
else {
|
|
144
|
-
throw new Error('Handler did not return an XapiRoot instance');
|
|
145
|
-
}
|
|
146
|
-
})
|
|
147
|
-
)
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
</pre></td></tr></table></pre>
|
|
151
|
-
|
|
152
|
-
<div class='push'></div><!-- for sticky footer -->
|
|
153
|
-
</div><!-- /wrapper -->
|
|
154
|
-
<div class='footer quiet pad2 space-top1 center small'>
|
|
155
|
-
Code coverage generated by
|
|
156
|
-
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
|
157
|
-
at 2025-07-05T15:46:50.456Z
|
|
158
|
-
</div>
|
|
159
|
-
<script src="prettify.js"></script>
|
|
160
|
-
<script>
|
|
161
|
-
window.onload = function () {
|
|
162
|
-
prettyPrint();
|
|
163
|
-
};
|
|
164
|
-
</script>
|
|
165
|
-
<script src="sorter.js"></script>
|
|
166
|
-
<script src="block-navigation.js"></script>
|
|
167
|
-
</body>
|
|
168
|
-
</html>
|
|
169
|
-
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { CallHandler, ExecutionContext, Injectable, Logger, NestInterceptor } from "@nestjs/common";
|
|
2
|
-
import { parse } from "@xapi-js/core";
|
|
3
|
-
import { Observable } from "rxjs";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Interceptor that parses incoming XML request bodies into XapiRoot objects.
|
|
7
|
-
* This interceptor should be applied to routes that expect an `application/xml` content type
|
|
8
|
-
* and whose body contains X-API XML data.
|
|
9
|
-
*/
|
|
10
|
-
@Injectable()
|
|
11
|
-
export class XapiRequestInterceptor implements NestInterceptor {
|
|
12
|
-
private readonly logger: Logger = new Logger(XapiRequestInterceptor.name);
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Intercepts the incoming request to parse XML body.
|
|
16
|
-
* If the content type is `application/xml` and a body exists, it attempts to parse the body
|
|
17
|
-
* into an `XapiRoot` object and replaces the original request body with it.
|
|
18
|
-
* @param context - The execution context of the request.
|
|
19
|
-
* @param next - A `CallHandler` to invoke the next interceptor or the route handler.
|
|
20
|
-
* @returns An `Observable` that will eventually contain the response.
|
|
21
|
-
*/
|
|
22
|
-
async intercept(context: ExecutionContext, next: CallHandler): Promise<Observable<any>> {
|
|
23
|
-
const request = context.switchToHttp().getRequest();
|
|
24
|
-
this.logger.debug(`XapiRequestInterceptor Intercepting request: ${request.method} ${request.url}`);
|
|
25
|
-
// Deserialize XML input to XapiRoot object
|
|
26
|
-
if (request.headers['content-type'] === 'application/xml' && request.body) {
|
|
27
|
-
request.body = await parse(request.body);
|
|
28
|
-
}
|
|
29
|
-
return next.handle()
|
|
30
|
-
}
|
|
31
|
-
}
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { CallHandler, ExecutionContext, Injectable, Logger, NestInterceptor } from '@nestjs/common';
|
|
2
|
-
import { XapiRoot, writeString } from '@xapi-js/core';
|
|
3
|
-
import { Observable, map } from 'rxjs';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Interceptor that serializes XapiRoot objects returned by NestJS route handlers into XML strings.
|
|
7
|
-
* This interceptor should be applied to routes that return an `XapiRoot` instance
|
|
8
|
-
* and whose response should be `application/xml`.
|
|
9
|
-
*/
|
|
10
|
-
@Injectable()
|
|
11
|
-
export class XapiResponseInterceptor implements NestInterceptor<XapiRoot, Promise<string>> {
|
|
12
|
-
private readonly logger: Logger = new Logger(XapiResponseInterceptor.name);
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Intercepts the outgoing response to serialize XapiRoot to XML string.
|
|
16
|
-
* If the handler returns an `XapiRoot` instance, it attempts to serialize it
|
|
17
|
-
* into an XML string.
|
|
18
|
-
* @param context - The execution context of the request.
|
|
19
|
-
* @param next - A `CallHandler` to invoke the next interceptor or the route handler.
|
|
20
|
-
* @returns An `Observable` that will eventually contain the XML string response.
|
|
21
|
-
* @throws {Error} if the handler does not return an `XapiRoot` instance or serialization fails.
|
|
22
|
-
*/
|
|
23
|
-
intercept(context: ExecutionContext, next: CallHandler): Observable<Promise<string>> {
|
|
24
|
-
this.logger.debug(`XapiResponseInterceptor Intercepting response`);
|
|
25
|
-
return next.handle().pipe(
|
|
26
|
-
map(async (value) => {
|
|
27
|
-
if (value instanceof XapiRoot) {
|
|
28
|
-
try {
|
|
29
|
-
// Serialize XapiRoot output to XML string
|
|
30
|
-
const xmlOutput = await writeString(value as XapiRoot);
|
|
31
|
-
return xmlOutput!!;
|
|
32
|
-
} catch (error) {
|
|
33
|
-
this.logger.error(`Failed to serialize XapiRoot to XML string: ${error.message}`);
|
|
34
|
-
throw error; // Re-throw the original error
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
else {
|
|
38
|
-
throw new Error('Handler did not return an XapiRoot instance');
|
|
39
|
-
}
|
|
40
|
-
})
|
|
41
|
-
)
|
|
42
|
-
}
|
|
43
|
-
}
|
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi } from 'vitest';
|
|
2
|
-
import { of, firstValueFrom } from 'rxjs';
|
|
3
|
-
import { XapiRequestInterceptor } from '../src/xapi-request-interceptor';
|
|
4
|
-
import { CallHandler, ExecutionContext } from '@nestjs/common';
|
|
5
|
-
import { XapiRoot } from '@xapi-js/core';
|
|
6
|
-
|
|
7
|
-
describe('XapiRequestInterceptor', () => {
|
|
8
|
-
let interceptor: XapiRequestInterceptor;
|
|
9
|
-
|
|
10
|
-
beforeEach(() => {
|
|
11
|
-
interceptor = new XapiRequestInterceptor();
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
it('should be defined', () => {
|
|
15
|
-
expect(interceptor).toBeDefined();
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
it('should deserialize Nexacro XAPI XML input to XapiRoot object', async () => {
|
|
19
|
-
const nexacroXmlInput = `<?xml version="1.0" encoding="UTF-8"?>
|
|
20
|
-
<Root xmlns="http://www.tobesoft.com/platform/Dataset" ver="4000">
|
|
21
|
-
<Dataset id="test">
|
|
22
|
-
<ColumnInfo>
|
|
23
|
-
<Column id="intCol" size="10" type="INT" />
|
|
24
|
-
<Column id="stringCol" size="50" type="STRING" />
|
|
25
|
-
</ColumnInfo>
|
|
26
|
-
<Rows>
|
|
27
|
-
<Row>
|
|
28
|
-
<Col id="intCol">123</Col>
|
|
29
|
-
<Col id="stringCol">hello</Col>
|
|
30
|
-
</Row>
|
|
31
|
-
<Row>
|
|
32
|
-
<Col id="intCol">456</Col>
|
|
33
|
-
<Col id="stringCol">world</Col>
|
|
34
|
-
</Row>
|
|
35
|
-
</Rows>
|
|
36
|
-
</Dataset>
|
|
37
|
-
</Root>`;
|
|
38
|
-
|
|
39
|
-
const mockRequest = {
|
|
40
|
-
body: nexacroXmlInput,
|
|
41
|
-
headers: { 'content-type': 'application/xml' },
|
|
42
|
-
};
|
|
43
|
-
const mockContext = {
|
|
44
|
-
switchToHttp: () => ({
|
|
45
|
-
getRequest: () => mockRequest,
|
|
46
|
-
getResponse: () => ({}),
|
|
47
|
-
}),
|
|
48
|
-
} as ExecutionContext;
|
|
49
|
-
|
|
50
|
-
const mockCallHandler = {
|
|
51
|
-
handle: () => of({}), // Mock a successful handler call
|
|
52
|
-
} as CallHandler;
|
|
53
|
-
|
|
54
|
-
const observableResult = await interceptor.intercept(mockContext, mockCallHandler);
|
|
55
|
-
await firstValueFrom(observableResult);
|
|
56
|
-
const request = mockContext.switchToHttp().getRequest();
|
|
57
|
-
|
|
58
|
-
expect(request.body).toBeInstanceOf(XapiRoot);
|
|
59
|
-
expect(request.body.datasets).toBeDefined();
|
|
60
|
-
expect(request.body.getDataset('test')).toBeDefined();
|
|
61
|
-
const dataset = request.body.getDataset('test');
|
|
62
|
-
expect(dataset.rows).toBeDefined();
|
|
63
|
-
expect(dataset.rows.length).toBe(2);
|
|
64
|
-
expect(dataset.getColumn(0, 'intCol')).toBe(123);
|
|
65
|
-
expect(dataset.getColumn(0, 'stringCol')).toBe('hello');
|
|
66
|
-
expect(dataset.getColumn(1, 'intCol')).toBe(456);
|
|
67
|
-
expect(dataset.getColumn(1, 'stringCol')).toBe('world');
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
it('should not deserialize non-XML input', async () => {
|
|
71
|
-
const jsonInput = `{ "data": "test" }`;
|
|
72
|
-
const mockRequest = {
|
|
73
|
-
body: jsonInput,
|
|
74
|
-
headers: { 'content-type': 'application/json' },
|
|
75
|
-
};
|
|
76
|
-
const mockContext = {
|
|
77
|
-
switchToHttp: () => ({
|
|
78
|
-
getRequest: () => mockRequest,
|
|
79
|
-
getResponse: () => ({}),
|
|
80
|
-
}),
|
|
81
|
-
} as ExecutionContext;
|
|
82
|
-
|
|
83
|
-
const mockCallHandler = {
|
|
84
|
-
handle: () => of({}),
|
|
85
|
-
} as CallHandler;
|
|
86
|
-
|
|
87
|
-
const observableResult = await interceptor.intercept(mockContext, mockCallHandler);
|
|
88
|
-
await firstValueFrom(observableResult);
|
|
89
|
-
const request = mockContext.switchToHttp().getRequest();
|
|
90
|
-
expect(request.body).toBe(jsonInput);
|
|
91
|
-
expect(request.body).not.toBeInstanceOf(XapiRoot);
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
it('should pass through if no body is present', async () => {
|
|
95
|
-
const mockRequest = {
|
|
96
|
-
headers: { 'content-type': 'application/xml' },
|
|
97
|
-
};
|
|
98
|
-
const mockContext = {
|
|
99
|
-
switchToHttp: () => ({
|
|
100
|
-
getRequest: () => mockRequest,
|
|
101
|
-
getResponse: () => ({}),
|
|
102
|
-
}),
|
|
103
|
-
} as ExecutionContext;
|
|
104
|
-
|
|
105
|
-
const mockCallHandler = {
|
|
106
|
-
handle: () => of({}),
|
|
107
|
-
} as CallHandler;
|
|
108
|
-
|
|
109
|
-
const observableResult = await interceptor.intercept(mockContext, mockCallHandler);
|
|
110
|
-
await firstValueFrom(observableResult);
|
|
111
|
-
const request = mockContext.switchToHttp().getRequest();
|
|
112
|
-
expect(request.body).toBeUndefined();
|
|
113
|
-
});
|
|
114
|
-
});
|
|
115
|
-
|
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi } from 'vitest';
|
|
2
|
-
import { of, firstValueFrom } from 'rxjs';
|
|
3
|
-
import { XapiResponseInterceptor } from '../src/xapi-response-interceptor';
|
|
4
|
-
import { CallHandler, ExecutionContext } from '@nestjs/common';
|
|
5
|
-
import { XapiRoot, Dataset, Column, writeString } from '@xapi-js/core';
|
|
6
|
-
|
|
7
|
-
// Mock the writeString function from @xapi-js/core
|
|
8
|
-
vi.mock('@xapi-js/core', async (importOriginal) => {
|
|
9
|
-
const actual = await importOriginal();
|
|
10
|
-
return {
|
|
11
|
-
...actual,
|
|
12
|
-
writeString: vi.fn(actual.writeString), // Use the actual implementation for mocking
|
|
13
|
-
};
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
describe('XapiResponseInterceptor', () => {
|
|
17
|
-
let interceptor: XapiResponseInterceptor;
|
|
18
|
-
|
|
19
|
-
beforeEach(() => {
|
|
20
|
-
interceptor = new XapiResponseInterceptor();
|
|
21
|
-
// Reset the mock before each test
|
|
22
|
-
vi.mocked(writeString).mockClear(); // Use writeString directly
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
it('should be defined', () => {
|
|
26
|
-
expect(interceptor).toBeDefined();
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
it('should serialize XapiRoot output to Nexacro XAPI XML string', async () => {
|
|
30
|
-
const xapiRootOutput = new XapiRoot();
|
|
31
|
-
const dataset = new Dataset('test');
|
|
32
|
-
dataset.addColumn({ id: 'intCol', size: 10, type: 'INT' });
|
|
33
|
-
dataset.addColumn({ id: 'stringCol', size: 50, type: 'STRING' });
|
|
34
|
-
|
|
35
|
-
dataset.newRow();
|
|
36
|
-
dataset.setColumn(0, 'intCol', 123);
|
|
37
|
-
dataset.setColumn(0, 'stringCol', 'hello');
|
|
38
|
-
|
|
39
|
-
dataset.newRow();
|
|
40
|
-
dataset.setColumn(1, 'intCol', 456);
|
|
41
|
-
dataset.setColumn(1, 'stringCol', 'world');
|
|
42
|
-
|
|
43
|
-
xapiRootOutput.addDataset(dataset);
|
|
44
|
-
|
|
45
|
-
const mockContext = {
|
|
46
|
-
switchToHttp: () => ({
|
|
47
|
-
getRequest: () => ({}),
|
|
48
|
-
getResponse: () => ({}),
|
|
49
|
-
}),
|
|
50
|
-
} as ExecutionContext;
|
|
51
|
-
|
|
52
|
-
const mockCallHandler = {
|
|
53
|
-
handle: () => of(xapiRootOutput),
|
|
54
|
-
} as CallHandler;
|
|
55
|
-
|
|
56
|
-
const observableResult = interceptor.intercept(mockContext, mockCallHandler);
|
|
57
|
-
const result = await firstValueFrom(observableResult);
|
|
58
|
-
expect(typeof result).toBe('string');
|
|
59
|
-
expect(result).toContain('<Root xmlns="http://www.nexacroplatform.com/platform/dataset" version="4000">');
|
|
60
|
-
expect(result).toContain('<Dataset id="test">');
|
|
61
|
-
expect(result).toMatch(/<Column id="intCol" size="10" type="INT"\s*\/>/);
|
|
62
|
-
expect(result).toMatch(/<Column id="stringCol" size="50" type="STRING"\s*\/>/);
|
|
63
|
-
expect(result).toContain('<Rows>');
|
|
64
|
-
expect(result).toContain('<Row>');
|
|
65
|
-
expect(result).toContain('<Col id="intCol">123</Col>');
|
|
66
|
-
expect(result).toContain('<Col id="stringCol">hello</Col>');
|
|
67
|
-
expect(result).toContain('<Col id="intCol">456</Col>');
|
|
68
|
-
expect(result).toContain('<Col id="stringCol">world</Col>');
|
|
69
|
-
expect(result).toContain('</Row>');
|
|
70
|
-
expect(result).toContain('</Rows>');
|
|
71
|
-
expect(result).toContain('</Dataset>');
|
|
72
|
-
expect(result).toContain('</Root>');
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
it('should throw an error if handler does not return XapiRoot', async () => {
|
|
76
|
-
const nonXapiRootOutput = { message: 'hello' };
|
|
77
|
-
|
|
78
|
-
const mockContext = {
|
|
79
|
-
switchToHttp: () => ({
|
|
80
|
-
getRequest: () => ({}),
|
|
81
|
-
getResponse: () => ({}),
|
|
82
|
-
}),
|
|
83
|
-
} as ExecutionContext;
|
|
84
|
-
|
|
85
|
-
const mockCallHandler = {
|
|
86
|
-
handle: () => of(nonXapiRootOutput),
|
|
87
|
-
} as CallHandler;
|
|
88
|
-
|
|
89
|
-
const observableResult = interceptor.intercept(mockContext, mockCallHandler);
|
|
90
|
-
await expect(firstValueFrom(observableResult)).rejects.toThrow('Handler did not return an XapiRoot instance');
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
it('should re-throw error from writeString', async () => {
|
|
94
|
-
const xapiRootOutput = new XapiRoot();
|
|
95
|
-
|
|
96
|
-
const mockContext = {
|
|
97
|
-
switchToHttp: () => ({
|
|
98
|
-
getRequest: () => ({}),
|
|
99
|
-
getResponse: () => ({}),
|
|
100
|
-
}),
|
|
101
|
-
} as ExecutionContext;
|
|
102
|
-
|
|
103
|
-
const mockCallHandler = {
|
|
104
|
-
handle: () => of(xapiRootOutput),
|
|
105
|
-
} as CallHandler;
|
|
106
|
-
|
|
107
|
-
const testError = new Error('Test writeString error');
|
|
108
|
-
vi.mocked(writeString).mockRejectedValue(testError);
|
|
109
|
-
|
|
110
|
-
const observableResult = interceptor.intercept(mockContext, mockCallHandler);
|
|
111
|
-
await expect(firstValueFrom(observableResult)).rejects.toThrow(testError);
|
|
112
|
-
});
|
|
113
|
-
});
|
package/vitest.config.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { defineConfig } from 'vitest/config'
|
|
2
|
-
|
|
3
|
-
export default defineConfig({
|
|
4
|
-
test: {
|
|
5
|
-
globals: true,
|
|
6
|
-
pool: "threads",
|
|
7
|
-
exclude: [
|
|
8
|
-
"**/node_modules/**",
|
|
9
|
-
"**/coverage/**",
|
|
10
|
-
"**/dist/**",
|
|
11
|
-
'**/.{idea,git,cache,output,temp}/**',
|
|
12
|
-
'**/{karma,rollup,webpack,vite,vitest,jest,ava,babel,nyc,cypress,tsup,build}.config.*',
|
|
13
|
-
],
|
|
14
|
-
include: ['test/**/*.test.ts'],
|
|
15
|
-
},
|
|
16
|
-
})
|