@labdigital/commercetools-mock 0.5.14 → 0.5.17

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.
@@ -0,0 +1 @@
1
+ export declare const maskSecretValue: <T>(resource: T, path: string) => T;
@@ -4,6 +4,8 @@ import { AbstractStorage } from '../storage';
4
4
  export declare type QueryParams = {
5
5
  expand?: string[];
6
6
  where?: string[];
7
+ offset?: number;
8
+ limit?: number;
7
9
  };
8
10
  export declare type GetParams = {
9
11
  expand?: string[];
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.5.14",
2
+ "version": "0.5.17",
3
3
  "license": "MIT",
4
4
  "main": "dist/index.js",
5
5
  "typings": "dist/index.d.ts",
@@ -0,0 +1,22 @@
1
+ import { json } from 'express'
2
+
3
+ export const maskSecretValue = <T>(resource: T, path: string): T => {
4
+ const parts = path.split('.')
5
+ const clone = JSON.parse(JSON.stringify(resource))
6
+ let val = clone
7
+
8
+ const target = parts.pop()
9
+ for (let i = 0; i < parts.length; i++) {
10
+ const part = parts[i]
11
+ val = val[part]
12
+
13
+ if (val == undefined) {
14
+ return resource
15
+ }
16
+ }
17
+
18
+ if (val && target && val[target]) {
19
+ val[target] = '****'
20
+ }
21
+ return clone
22
+ }
@@ -14,6 +14,8 @@ import { CommercetoolsError } from '../exceptions'
14
14
  export type QueryParams = {
15
15
  expand?: string[]
16
16
  where?: string[]
17
+ offset?: number
18
+ limit?: number
17
19
  }
18
20
 
19
21
  export type GetParams = {
@@ -69,6 +71,8 @@ export abstract class AbstractResourceRepository extends AbstractRepository {
69
71
  return this._storage.query(projectKey, this.getTypeId(), {
70
72
  expand: params.expand,
71
73
  where: params.where,
74
+ offset: params.offset,
75
+ limit: params.limit,
72
76
  })
73
77
  }
74
78
 
@@ -50,10 +50,13 @@ export class ProductProjectionRepository extends AbstractResourceRepository {
50
50
  }
51
51
 
52
52
  search(projectKey: string, query: ParsedQs) {
53
- const wherePredicate = parseFilterExpression(query.filter as any)
53
+ const filter = (query['filter.query'] ?? query.filter) as any
54
+ const wherePredicate = filter ? parseFilterExpression(filter) : undefined
54
55
 
55
56
  const results = this._storage.query(projectKey, this.getTypeId(), {
56
57
  where: wherePredicate,
58
+ offset: query.offset ? Number(query.offset) : undefined,
59
+ limit: query.limit ? Number(query.limit) : undefined,
57
60
  }) //TODO: this is a partial implementation, but I don't really have the time to implement an actual search API right now
58
61
 
59
62
  return results
@@ -18,11 +18,17 @@ import { Writable } from 'types'
18
18
  import { checkConcurrentModification } from './errors'
19
19
  import { CommercetoolsError } from '../exceptions'
20
20
  import { AbstractRepository } from './abstract'
21
+ import { maskSecretValue } from '../lib/masking'
21
22
 
22
23
  export class ProjectRepository extends AbstractRepository {
23
24
  get(projectKey: string): Project | null {
24
25
  const data = this._storage.getProject(projectKey)
25
- return this._storage.getProject(projectKey)
26
+ const resource = this._storage.getProject(projectKey)
27
+ const masked = maskSecretValue<Project>(
28
+ resource,
29
+ 'externalOAuth.authorizationHeader'
30
+ )
31
+ return masked
26
32
  }
27
33
 
28
34
  save(projectKey: string, resource: Project) {
@@ -37,9 +37,14 @@ export default abstract class AbstractService {
37
37
  }
38
38
 
39
39
  get(request: Request, response: Response) {
40
+ const limit = this._parseParam(request.query.limit)
41
+ const offset = this._parseParam(request.query.offset)
42
+
40
43
  const result = this.repository.query(request.params.projectKey, {
41
44
  expand: this._parseParam(request.query.expand),
42
45
  where: this._parseParam(request.query.where),
46
+ limit: limit !== undefined ? Number(limit) : undefined,
47
+ offset: offset !== undefined ? Number(offset) : undefined,
43
48
  })
44
49
  return response.status(200).send(result)
45
50
  }
@@ -56,7 +56,20 @@ describe('Product Projection', () => {
56
56
  })
57
57
  })
58
58
 
59
- test('Search product projection', async () => {
59
+ test('Get product projection by 404 when not found by key with expand', async () => {
60
+ const response = await supertest(ctMock.app).get(
61
+ '/dummy/product-projections/key=DOESNOTEXIST?' +
62
+ qs.stringify({
63
+ expand: ['categories[*]'],
64
+ })
65
+ )
66
+
67
+ expect(response.status).toBe(404)
68
+ })
69
+ })
70
+
71
+ describe('Product Projection Search', () => {
72
+ beforeAll(() => {
60
73
  ctMock.project('dummy').add('product-projection', {
61
74
  id: '',
62
75
  version: 1,
@@ -72,7 +85,9 @@ describe('Product Projection', () => {
72
85
  lastModifiedAt: '',
73
86
  categories: [],
74
87
  })
88
+ })
75
89
 
90
+ test('Search product projection', async () => {
76
91
  const response = await supertest(ctMock.app).get(
77
92
  '/dummy/product-projections/search?' +
78
93
  qs.stringify({
@@ -102,4 +117,51 @@ describe('Product Projection', () => {
102
117
  ],
103
118
  })
104
119
  })
120
+
121
+ test('Search product projection page 2', async () => {
122
+ const response = await supertest(ctMock.app).get(
123
+ '/dummy/product-projections/search?' +
124
+ qs.stringify({
125
+ filter: ['masterVariant.sku:"1337"'],
126
+ limit: 50,
127
+ offset: 100,
128
+ })
129
+ )
130
+
131
+ const projection: ProductProjection = response.body
132
+ expect(projection).toEqual({
133
+ count: 1,
134
+ limit: 50,
135
+ offset: 100,
136
+ total: 0,
137
+ results: [],
138
+ })
139
+ })
140
+
141
+ test('Search product projection with query.filter', async () => {
142
+ const response = await supertest(ctMock.app).get(
143
+ '/dummy/product-projections/search?' +
144
+ qs.stringify({
145
+ 'query.filter': ['masterVariant.sku:"1337"'],
146
+ })
147
+ )
148
+
149
+ const projection: ProductProjection = response.body
150
+ expect(projection).toMatchObject({
151
+ count: 1,
152
+ results: [{ masterVariant: { id: 1, sku: '1337' } }],
153
+ })
154
+ })
155
+
156
+ test('Search product projection without filter', async () => {
157
+ const response = await supertest(ctMock.app).get(
158
+ '/dummy/product-projections/search'
159
+ )
160
+
161
+ const projection: ProductProjection = response.body
162
+ expect(projection).toMatchObject({
163
+ count: 1,
164
+ results: [{ masterVariant: { id: 1, sku: '1337' } }],
165
+ })
166
+ })
105
167
  })
package/src/storage.ts CHANGED
@@ -211,8 +211,14 @@ export class InMemoryStorage extends AbstractStorage {
211
211
 
212
212
  const resources: any[] = Array.from(store.values())
213
213
  const resource = resources.find(e => e.key === key)
214
- if (params.expand) return this.expand(projectKey, resource, params.expand)
215
- return resource
214
+ if (resource) {
215
+ return this.expand(
216
+ projectKey,
217
+ resource,
218
+ params.expand
219
+ ) as ResourceMap[RepositoryTypes]
220
+ }
221
+ return null
216
222
  }
217
223
 
218
224
  delete(