Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions __tests__/components/__snapshots__/components.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,25 @@ Array [
]
`;

exports[`test Collect And Reveal Elements Components test RevealElement component rendering 1`] = `
Array [
<Text
style={Object {}}
>
Card Number
</Text>,
<Text
selectable={true}
style={Object {}}
>
XXXX XXXX XXXX XXXX
</Text>,
<Text
style={Object {}}
/>,
]
`;

exports[`test Collect And Reveal Elements Components test skyflow provider 1`] = `
<Text>
Provider Childern
Expand Down
79 changes: 79 additions & 0 deletions __tests__/components/components.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { Text } from 'react-native';
import SkyflowError from '../../src/utils/skyflow-error';
import SKYFLOW_ERROR_CODE from '../../src/utils/skyflow-error-code';
import { ContainerType, ElementType } from '../../src/utils/constants';
import { act } from 'react-test-renderer';

const testSkyflowClient = new Skyflow({
vaultID: '1234',
Expand Down Expand Up @@ -598,6 +599,84 @@ describe('test Collect And Reveal Elements Components', () => {
}
});

it('test RevealElement component rendering', () => {
const revealSetMethodMock = jest.fn();
const revealSetTokenMock = jest.fn();
const revealContainer = new RevealContainer(testSkyflowClient);

jest.spyOn(revealContainer, 'create').mockImplementation(() => ({
setMethods: revealSetMethodMock,
setToken: revealSetTokenMock,
}));

const revealElement = render(
<RevealElement
token={'test_token'}
container={revealContainer}
label={'Card Number'}
altText={'XXXX XXXX XXXX XXXX'}
/>
);

expect(revealElement).toMatchSnapshot();
expect(revealSetMethodMock).toBeCalledTimes(1);

render(
<RevealElement
token={'test_token_no_alt'}
container={revealContainer}
label={'Card Number'}
/>
);
expect(screen.getByText('test_token_no_alt')).toBeTruthy();

try {
render(<RevealElement token={'test_token'} label={'Card Number'} />);
} catch (err) {
expect(err).toEqual(
new SkyflowError(
SKYFLOW_ERROR_CODE.CONTAINER_OBJECT_IS_REQUIRED,
['Reveal', 'useRevealContainer()'],
true
)
);
}
});

it('test RevealElement setToken via ref updates UI and internal element', () => {
const revealSetMethodMock = jest.fn();
const revealSetTokenMock = jest.fn();
const revealContainer = new RevealContainer(testSkyflowClient);

jest.spyOn(revealContainer, 'create').mockImplementation(() => ({
setMethods: revealSetMethodMock,
setToken: revealSetTokenMock,
}));

const ref = React.createRef();
const initialToken = 'initial_token_123';
const newToken = 'updated_token_456';

const { getByText } = render(
<RevealElement
ref={ref}
token={initialToken}
container={revealContainer}
label={'Card Number'}
/>
);

expect(getByText(initialToken)).toBeTruthy();

act(() => {
ref.current.setToken(newToken);
});

expect(revealSetTokenMock).toHaveBeenCalledWith(newToken);

expect(getByText(newToken)).toBeTruthy();
});

it('test skyflow provider', () => {
const testSkyflowConfig = {
vaultID: '1234',
Expand Down
52 changes: 52 additions & 0 deletions __tests__/core/RevealContainer.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -146,4 +146,56 @@ describe('test RevealConatiner Class', () => {
}
});
});

it('test reveal method uses updated token when setToken is called', (done) => {
const initialToken = 'initial_token';
const updatedToken = 'updated_token';

const revealElement = revealContainer.create({
token: initialToken,
});

const revealSuccessValue = {
records: [
{
token: updatedToken,
value: 'revealed_value',
},
],
};

const fetchSpy = jest
.spyOn(revealUtils, 'fetchRecordsByTokenId')
.mockResolvedValue(revealSuccessValue);

const setValueMock = jest.fn();
const setErrorMock = jest.fn();
revealElement.setMethods(setValueMock, setErrorMock);

revealElement.setToken(updatedToken);

revealContainer
.reveal()
.then((res) => {
try {
expect(fetchSpy).toHaveBeenCalledWith(
expect.anything(),
expect.arrayContaining([
expect.objectContaining({
token: updatedToken,
elementId: revealElement.elementId,
}),
])
);

expect(res).toEqual({ success: [{ token: updatedToken }] });
done();
} catch (assertionError) {
done(assertionError);
}
})
.catch((err) => {
done(err);
});
});
});
32 changes: 22 additions & 10 deletions src/components/RevealElement/index.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
/*
Copyright (c) 2022 Skyflow, Inc.
*/
import React, { useEffect } from "react";
import React, { useEffect, useImperativeHandle, forwardRef } from "react";
import { Text } from "react-native";
import RevealSkyflowElement from "../../core/RevealSkyflowElement";
import { RevealElementProps } from "../../utils/constants"
import SkyflowError from "../../utils/skyflow-error";
import SKYFLOW_ERROR_CODE from "../../utils/skyflow-error-code";


const RevealElement: React.FC<RevealElementProps> = ({ container, label, ...rest }) => {
const [element, setElement] = React.useState<RevealSkyflowElement>(undefined);
const RevealElement = forwardRef((props: RevealElementProps, ref) => {
const { container, label, ...rest } = props;
const [element, setElement] = React.useState<RevealSkyflowElement | undefined>(undefined);
const [errorText, setErrorText] = React.useState<string>('');
const [value, setValue] = React.useState(rest?.altText || rest.token);

Expand All @@ -25,12 +25,24 @@ const RevealElement: React.FC<RevealElementProps> = ({ container, label, ...rest

}, []);

return <>
<Text style={rest.labelStyles?.base || {}}>{label}</Text>
<Text selectable style={rest?.inputStyles?.base || {}}>{value}</Text>
<Text style={rest?.errorTextStyles?.base || {}}>{errorText}</Text>
</>
useImperativeHandle(ref, () => ({
setToken: (newToken: string) => {
if (element) {
element.setToken(newToken);
setValue(newToken);
} else {
throw new SkyflowError(SKYFLOW_ERROR_CODE.ELEMENT_NOT_FOUND, ['RevealElement'], true);
}
}
}), [element]);

}
return (
<>
<Text style={rest.labelStyles?.base || {}}>{label}</Text>
<Text selectable style={rest?.inputStyles?.base || {}}>{value}</Text>
<Text style={rest?.errorTextStyles?.base || {}}>{errorText}</Text>
</>
);
});

export default RevealElement;
17 changes: 16 additions & 1 deletion src/core/RevealContainer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,22 @@ class RevealContainer extends Container {
try {
validateInitConfig(this.#skyflowClient.getSkyflowConfig());
validateRevealElementRecords(this.#revealRecords);
fetchRecordsByTokenId(this.#skyflowClient, this.#tokensList).then(

const freshTokensList = this.#tokensList.map((record) => {
const elementInstance = this.#elementList.find(
(e) => e.elementId === record.elementId
);

if (elementInstance) {
return {
...record,
token: elementInstance.getToken(),
};
}
return record;
});

fetchRecordsByTokenId(this.#skyflowClient, freshTokensList).then(
(resolvedResult) => {
const formattedResult = formatRecordsForIframe(resolvedResult);
this.setRevealValuesInElements(formattedResult);
Expand Down
4 changes: 4 additions & 0 deletions src/core/RevealSkyflowElement/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ class RevealSkyflowElement extends SkyflowElement {
this.#setErrorText(REVEAL_ELEMENT_ERROR_TEXT);
}

setToken(newToken: string) {
this.#token = newToken;
}

getToken() {
return this.#token;
}
Expand Down
2 changes: 2 additions & 0 deletions src/utils/logs/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ const logs = {
`Skyflow ${SDK_NAME_VERSION} initialization failed - SkyflowProvider config is missing. `,
CONTAINER_OBJECT_IS_REQUIRED:
`${SDK_NAME_VERSION} cannot create %s1 element without container object, create a container using %s2 hook.`,
ELEMENT_NOT_FOUND:
`${SDK_NAME_VERSION} %s1 not found. The specified element does not exist in the container.`,
INVALID_UPSERT_OPTION_TYPE:
`${SDK_NAME_VERSION} Validation error. Invalid \'upsert\' key in insert options. Specify a value of type array instead`,
EMPTY_UPSERT_OPTIONS_ARRAY:
Expand Down
4 changes: 4 additions & 0 deletions src/utils/skyflow-error-code/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,10 @@ const SKYFLOW_ERROR_CODE = {
code: 400,
description: logs.errorLogs.CONTAINER_OBJECT_IS_REQUIRED,
},
ELEMENT_NOT_FOUND: {
code: 400,
description: logs.errorLogs.ELEMENT_NOT_FOUND,
},
INVALID_UPSERT_OPTION_TYPE: {
code: 400,
description: logs.errorLogs.INVALID_UPSERT_OPTION_TYPE,
Expand Down