Skip to content

Commit

Permalink
feat: enhance construct elementString (#103)
Browse files Browse the repository at this point in the history
* feat: implement concat service that can apply to the identifierKeyPath config

Signed-off-by: Nam Hoang <[email protected]>

* test: add test for adding services

Signed-off-by: Nam Hoang <[email protected]>

* chore: remove comment

Signed-off-by: Nam Hoang <[email protected]>

* refactor: handle elementString missing AI code

Signed-off-by: Nam Hoang <[email protected]>

* feat: remove the local storage used data for the process DPP

Signed-off-by: Nam Hoang <[email protected]>

* docs: add document for identifierKeyPath

Signed-off-by: Nam Hoang <[email protected]>

* refactor: handle exception case for construct identifier

Signed-off-by: Nam Hoang <[email protected]>

* test: add test for local storage service

Signed-off-by: Nam Hoang <[email protected]>

---------

Signed-off-by: Nam Hoang <[email protected]>
  • Loading branch information
namhoang1604 authored Sep 23, 2024
1 parent 0a0d949 commit 2ab5d12
Show file tree
Hide file tree
Showing 15 changed files with 537 additions and 57 deletions.
45 changes: 45 additions & 0 deletions documentation/docs/mock-apps/common/identifier-key-path.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
---
sidebar_position: 40
title: Identify Key Path
---

import Disclaimer from '../.././\_disclaimer.mdx';

<Disclaimer />

## Description

The `IdentifierKeyPath` is a property of services that interact with the data issued to get the identifier to be used for the [IDR](/docs/mock-apps/common/idr) registration. It can be a JSON path of the identifier of the data issued or an object that contains the function `concatService` and the `args` to be used to get the identifier.

## Example

```json
{
"identifierKeyPath": "/eventID"
}
```

or

```json
{
"identifierKeyPath": {
"function": "concatService",
"args": [
{ "type": "text", "value": "(01)" },
{ "type": "path", "value": "/productIdentifier/0/identifierValue" },
{ "type": "text", "value": "(10)" },
{ "type": "path", "value": "/batchIdentifier/0/identifierValue" },
{ "type": "text", "value": "(21)" },
{ "type": "path", "value": "/itemIdentifier/0/identifierValue" }
]
}
}
```

## Definition for object

| Property | Required | Description | Type |
| -------- | :------: | ------------------------------------------------ | ------ |
| function | Yes | The concat function supported | String |
| args | Yes | The array of object that can be `text` or `path` | Array |
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ sidebar_position: 26
title: Process Aggregation Event
---

import Disclaimer from '../../_disclaimer.mdx';
import Disclaimer from '../../\_disclaimer.mdx';

<Disclaimer />

Expand Down Expand Up @@ -74,10 +74,10 @@ P-->>C: Return VC and resolver URL

## Definitions

| Property | Required | Description | Type |
|----------|----------|-------------|------|
| vckit | Yes | Configuration for the VCKit service | [VCKit](/docs/mock-apps/common/vckit) |
| epcisAggregationEvent | Yes | Configuration for the EPCIS Aggregation Event | [Credential](/docs/mock-apps/common/credential) |
| storage | Yes | Configuration for storage service | [Storage](/docs/mock-apps/common/storage) |
| dlr | Yes | Configuration for the Digital Link Resolver | [IDR](/docs/mock-apps/common/idr) |
| identifierKeyPath | Yes | JSON path to the identifier in the credential subject | String |
| Property | Required | Description | Type |
| --------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------- |
| vckit | Yes | Configuration for the VCKit service | [VCKit](/docs/mock-apps/common/vckit) |
| epcisAggregationEvent | Yes | Configuration for the EPCIS Aggregation Event | [Credential](/docs/mock-apps/common/credential) |
| storage | Yes | Configuration for storage service | [Storage](/docs/mock-apps/common/storage) |
| dlr | Yes | Configuration for the Digital Link Resolver | [IDR](/docs/mock-apps/common/idr) |
| identifierKeyPath | Yes | JSON path to the identifier in the credential subject or the object for function and arguments of JSON path to construct identifier | [IdentifierKeyPath](/docs/mock-apps/common/identifier-key-path) |
17 changes: 8 additions & 9 deletions documentation/docs/mock-apps/services/process-dpp.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ sidebar_position: 23
title: Process DPP
---

import Disclaimer from '../../_disclaimer.mdx';
import Disclaimer from '../../\_disclaimer.mdx';

<Disclaimer />

Expand Down Expand Up @@ -98,11 +98,10 @@ P-->>C: Return VC and resolver URL

## Definitions

| Property | Required | Description | Type |
|----------|----------|-------------|------|
| vckit | Yes | Configuration for the VCKit service | [VCKit](/docs/mock-apps/common/vckit) |
| dpp | Yes | Configuration for the Digital Product Passport | [DPP](/docs/mock-apps/common/credential) |
| dlr | Yes | Configuration for the Digital Link Resolver | [IDR](/docs/mock-apps/common/idr) |
| storage | Yes | Configuration for storage service | [Storage](/docs/mock-apps/common/storage) |
| identifierKeyPath | Yes | JSON path to the identifier in the credential subject | String |

| Property | Required | Description | Type |
| ----------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------- |
| vckit | Yes | Configuration for the VCKit service | [VCKit](/docs/mock-apps/common/vckit) |
| dpp | Yes | Configuration for the Digital Product Passport | [DPP](/docs/mock-apps/common/credential) |
| dlr | Yes | Configuration for the Digital Link Resolver | [IDR](/docs/mock-apps/common/idr) |
| storage | Yes | Configuration for storage service | [Storage](/docs/mock-apps/common/storage) |
| identifierKeyPath | Yes | JSON path to the identifier in the credential subject or the object for function and arguments of JSON path to construct identifier | [IdentifierKeyPath](/docs/mock-apps/common/identifier-key-path) |
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ sidebar_position: 24
title: Process Transaction Event
---

import Disclaimer from '../../_disclaimer.mdx';
import Disclaimer from '../../\_disclaimer.mdx';

<Disclaimer />

Expand Down Expand Up @@ -80,11 +80,11 @@ P-->>C: Return VC and resolver URL

## Definitions

| Property | Required | Description | Type |
|----------|----------|-------------|------|
| vckit | Yes | Configuration for the VCKit service | [VCKit](/docs/mock-apps/common/vckit) |
| epcisTransactionEvent | Yes | Configuration for the EPCIS Transaction Event | [Credential](/docs/mock-apps/common/credential) |
| storage | Yes | Configuration for storage service | [Storage](/docs/mock-apps/common/storage) |
| dlr | Yes | Configuration for the Digital Link Resolver | [IDR](/docs/mock-apps/common/idr) |
| identifierKeyPath | Yes | JSON path to the identifier in the credential subject | String |
| localStorageParams | Yes | Configuration for local storage management | [LocalStorage](/docs/mock-apps/common/local-storage) |
| Property | Required | Description | Type |
| --------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------- |
| vckit | Yes | Configuration for the VCKit service | [VCKit](/docs/mock-apps/common/vckit) |
| epcisTransactionEvent | Yes | Configuration for the EPCIS Transaction Event | [Credential](/docs/mock-apps/common/credential) |
| storage | Yes | Configuration for storage service | [Storage](/docs/mock-apps/common/storage) |
| dlr | Yes | Configuration for the Digital Link Resolver | [IDR](/docs/mock-apps/common/idr) |
| identifierKeyPath | Yes | JSON path to the identifier in the credential subject or the object for function and arguments of JSON path to construct identifier | [IdentifierKeyPath](/docs/mock-apps/common/identifier-key-path) |
| localStorageParams | Yes | Configuration for local storage management | [LocalStorage](/docs/mock-apps/common/local-storage) |
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ sidebar_position: 25
title: Process Transformation Event
---

import Disclaimer from '../../_disclaimer.mdx';
import Disclaimer from '../../\_disclaimer.mdx';

<Disclaimer />
<!-- TODO: Confirm the system does delete the transaction events from local storage. If so, update diagram. -->
Expand Down Expand Up @@ -126,13 +126,13 @@ P-->>C: Return EPCIS VC

## Definitions

| Property | Required | Description | Type |
|----------|----------|-------------|------|
| vckit | Yes | Configuration for the VCKit service | [VCKit](/docs/mock-apps/common/vckit) |
| epcisTransformationEvent | Yes | Configuration for the EPCIS Transformation Event | [Credential](/docs/mock-apps/common/credential) |
| dlr | Yes | Configuration for the Digital Link Resolver | [IDR](/docs/mock-apps/common/idr) |
| storage | Yes | Configuration for storage service | [Storage](/docs/mock-apps/common/storage) |
| dpp | Yes | Configuration for the Digital Product Passport | [Credential](/docs/mock-apps/common/credential) |
| dppCredentials | Yes | Mapping configuration for DPP credentials | [Construct Data](/docs/mock-apps/common/construct-data)[] |
| identifierKeyPath | Yes | JSON path to the identifier in the credential subject | String |
| transformationEventCredential | Yes | Mapping and generation configuration for the transformation event credential | [Construct Data](/docs/mock-apps/common/construct-data) |
| Property | Required | Description | Type |
| ----------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------- |
| vckit | Yes | Configuration for the VCKit service | [VCKit](/docs/mock-apps/common/vckit) |
| epcisTransformationEvent | Yes | Configuration for the EPCIS Transformation Event | [Credential](/docs/mock-apps/common/credential) |
| dlr | Yes | Configuration for the Digital Link Resolver | [IDR](/docs/mock-apps/common/idr) |
| storage | Yes | Configuration for storage service | [Storage](/docs/mock-apps/common/storage) |
| dpp | Yes | Configuration for the Digital Product Passport | [Credential](/docs/mock-apps/common/credential) |
| dppCredentials | Yes | Mapping configuration for DPP credentials | [Construct Data](/docs/mock-apps/common/construct-data)[] |
| identifierKeyPath | Yes | JSON path to the identifier in the credential subject or the object for function and arguments of JSON path to construct identifier | [IdentifierKeyPath](/docs/mock-apps/common/identifier-key-path) |
| transformationEventCredential | Yes | Mapping and generation configuration for the transformation event credential | [Construct Data](/docs/mock-apps/common/construct-data) |
3 changes: 2 additions & 1 deletion packages/services/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"scripts": {
"build": "tsc --build --clean && tsc",
"watch": "tsc -b --watch",
"test": "jest --ci --env=jest-environment-node",
"test": "jest --ci",
"test:coverage": "jest --coverage"
},
"type": "module",
Expand All @@ -34,6 +34,7 @@
"typescript": "^5.3.3"
},
"jest": {
"testEnvironment": "jsdom",
"testPathIgnorePatterns": [
"/node_modules/",
"/build/",
Expand Down
139 changes: 139 additions & 0 deletions packages/services/src/__tests__/features/localStorage.service.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
import {
deleteItemFromLocalStorage,
deleteValuesFromLocalStorage,
mergeToLocalStorage,
saveToLocalStorage,
} from '../../features/localStorage.service';

describe('saveToLocalStorage', () => {
afterEach(() => {
jest.restoreAllMocks();
});

it('should save the data to local storage', () => {
const spySetItem = jest.spyOn(Storage.prototype, 'setItem');
const data = { a: 1 };
const parameters = { storageKey: 'key' };
saveToLocalStorage(data, parameters);
expect(spySetItem).toHaveBeenCalledWith('key', JSON.stringify(data));
});

it('should throw an error if an error occurs', () => {
const spySetItem = jest.spyOn(Storage.prototype, 'setItem');
const data = { a: 1 };
const parameters = { storageKey: 'key' };
const error = new Error('An error occurred');
spySetItem.mockImplementationOnce(() => {
throw error;
});
expect(() => saveToLocalStorage(data, parameters)).toThrow(error);
});
});

describe('mergeToLocalStorage', () => {
afterEach(() => {
jest.restoreAllMocks();
});

it('should merge the data to local storage when not existing', () => {
const spyGetItem = jest.spyOn(Storage.prototype, 'getItem');
const spySetItem = jest.spyOn(Storage.prototype, 'setItem');
const data = { a: 1 };
const parameters = { storageKey: 'key', objectKeyPath: '/a' };
spyGetItem.mockReturnValueOnce(JSON.stringify(null));
mergeToLocalStorage(data, parameters);
expect(spySetItem).toHaveBeenCalledWith('key', JSON.stringify({ 1: { a: 1 } }));
});

it('should merge the data to local storage when existing', () => {
const spyGetItem = jest.spyOn(Storage.prototype, 'getItem');
const spySetItem = jest.spyOn(Storage.prototype, 'setItem');
const data = { a: 1 };
const parameters = { storageKey: 'key', objectKeyPath: '/a' };
spyGetItem.mockReturnValueOnce(JSON.stringify({ 2: { a: 2 } }));
mergeToLocalStorage(data, parameters);
expect(spySetItem).toHaveBeenCalledWith('key', JSON.stringify({ 2: { a: 2 }, 1: { a: 1 } }));
});

it('should throw error when invalid objectKeyPath is provided', () => {
const spyGetItem = jest.spyOn(Storage.prototype, 'getItem');
const data = { a: 1 };
const parameters = { storageKey: 'key', objectKeyPath: 'invalid' };
spyGetItem.mockReturnValueOnce(JSON.stringify({ a: 2 }));
expect(() => mergeToLocalStorage(data, parameters)).toThrow();
});

it('should throw an error if an error occurs', () => {
const spyGetItem = jest.spyOn(Storage.prototype, 'getItem');
const spySetItem = jest.spyOn(Storage.prototype, 'setItem');
const data = { a: 1 };
const parameters = { storageKey: 'key', objectKeyPath: '/a' };
const error = new Error('An error occurred');
spyGetItem.mockReturnValueOnce(JSON.stringify({ a: 2 }));
spySetItem.mockImplementationOnce(() => {
throw error;
});
expect(() => mergeToLocalStorage(data, parameters)).toThrow(error);
});
});

describe('deleteValuesFromLocalStorage', () => {
afterEach(() => {
jest.restoreAllMocks();
});

it('should delete the values from local storage', () => {
const spyGetItem = jest.spyOn(Storage.prototype, 'getItem');
const spySetItem = jest.spyOn(Storage.prototype, 'setItem');
const data = { a: 1, b: 2 };
const parameters = { storageKey: 'key', keys: ['a'] };
spyGetItem.mockReturnValueOnce(JSON.stringify(data));
deleteValuesFromLocalStorage(parameters);
expect(spySetItem).toHaveBeenCalledWith('key', JSON.stringify({ b: 2 }));
});

it('should not delete the values from local storage if the key does not exist', () => {
const spyGetItem = jest.spyOn(Storage.prototype, 'getItem');
const spySetItem = jest.spyOn(Storage.prototype, 'setItem');
const parameters = { storageKey: 'key', keys: ['a'] };
spyGetItem.mockReturnValueOnce(JSON.stringify({ b: 2 }));
deleteValuesFromLocalStorage(parameters);
expect(spySetItem).toHaveBeenCalledWith('key', JSON.stringify({ b: 2 }));
});

it('should throw an error if an error occurs', () => {
const spyGetItem = jest.spyOn(Storage.prototype, 'getItem');
const spySetItem = jest.spyOn(Storage.prototype, 'setItem');
const data = { a: 1, b: 2 };
const parameters = { storageKey: 'key', keys: ['a'] };
const error = new Error('An error occurred');
spyGetItem.mockReturnValueOnce(JSON.stringify(data));
spySetItem.mockImplementationOnce(() => {
throw error;
});
expect(() => deleteValuesFromLocalStorage(parameters)).toThrow(error);
});
});

describe('deleteItemFromLocalStorage', () => {
afterEach(() => {
jest.restoreAllMocks();
});

it('should delete the item from local storage', () => {
const spyRemoveItem = jest.spyOn(Storage.prototype, 'removeItem');
const parameters = { storageKey: 'key' };
deleteItemFromLocalStorage(parameters);
expect(spyRemoveItem).toHaveBeenCalledWith('key');
});

it('should throw an error if an error occurs', () => {
const spyRemoveItem = jest.spyOn(Storage.prototype, 'removeItem');
const parameters = { storageKey: 'key' };
const error = new Error('An error occurred');
spyRemoveItem.mockImplementationOnce(() => {
throw error;
});
expect(() => deleteItemFromLocalStorage(parameters)).toThrow(error);
});
});
Loading

0 comments on commit 2ab5d12

Please sign in to comment.