Skip to content
Open
Show file tree
Hide file tree
Changes from 4 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
7 changes: 5 additions & 2 deletions src/locales/en/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,7 @@
"bottomdescription": "If you’re ready and understand, please click the “Proceed to scan” button. This will open a scanner where you scan the QR code or manually enter the URL.",
"buttons": {
"connected": "Get connected",
"onboardingdocumentation": "Visit our website",
"onboardingdocumentation": "Visit our documentation",
"recoverydocumentation": "Recovery documentation"
}
},
Expand All @@ -426,7 +426,10 @@
},
"advancedsetup": {
"title": "Advanced setup",
"description": "To connect, please enter the SSI agent boot and connect URLs (in your email or from your command line).",
"description": {
"connectboot": "To connect, please enter the SSI agent boot and connect URLs (in your email or from your command line).",
"connect": "To connect, please enter the SSI agent connect URL (in your email or from your command line)."
},
"buttons": {
"connect": "Connect",
"cancel": "Cancel"
Expand Down
6 changes: 4 additions & 2 deletions src/ui/globals/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ const DOUBLE_TAP_DELAY = 300;
const SUPPORT_EMAIL = "mailto:[email protected]";
const WEBSITE_LINK = "https://www.veridian.id";
const DOCUMENTATION_LINK = "https://docs.veridian.id/";
const ONBOARDING_DOCUMENTATION_LINK = "https://docs.veridian.id/onboarding";
const RECOVERY_DOCUMENTATION_LINK = "https://docs.veridian.id/recovery";
const ONBOARDING_DOCUMENTATION_LINK =
"https://docs.veridian.id/onboarding#ssi-agent-details";
const RECOVERY_DOCUMENTATION_LINK =
"https://docs.veridian.id/recovery#ssi-agent-details";
const FEDERAL_DATA_PROTECTION_LINK = "https://www.edoeb.admin.ch/de";
const DATA_PROTECTION_AUTHORITIES_LINK =
"https://ec.europa.eu/justice/article-29/structure/data-protection-authorities/index_en.htm";
Expand Down
4 changes: 0 additions & 4 deletions src/ui/pages/CreateSSIAgent/CreateSSIAgent.scss
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,6 @@
}

.ssi-agent-scan-input-modal.responsive-modal {
&.loading {
z-index: -1 !important;
}

.buttons-last-slot {
min-width: auto !important;

Expand Down
264 changes: 262 additions & 2 deletions src/ui/pages/CreateSSIAgent/CreateSSIAgent.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const checkPermisson = jest.fn(() =>
const requestPermission = jest.fn();
const startScan = jest.fn();
const stopScan = jest.fn();
const getPlatformMock = jest.fn(() => ["mobile"]);
const discoverConnectUrlMock = jest.fn();

const customiseMockValue: {
identifiers: { creation: { individualOnly: string } };
Expand Down Expand Up @@ -133,6 +133,7 @@ jest.mock("../../../core/agent/agent", () => ({
agent: {
bootAndConnect: bootAndConnectMock,
recoverKeriaAgent: recoverKeriaAgentMock,
discoverConnectUrl: discoverConnectUrlMock,
basicStorage: {
deleteById: basicStorageDeleteMock,
createOrUpdateBasicRecord: createOrUpdateBasicRecordMock,
Expand Down Expand Up @@ -220,6 +221,12 @@ describe("SSI agent page", () => {
dispatch: dispatchMock,
};

beforeEach(() => {
discoverConnectUrlMock.mockImplementation(() =>
Promise.resolve(connectUrl)
);
});

describe("SSI connect summary", () => {
test("Render", async () => {
const { getByText } = render(
Expand Down Expand Up @@ -687,6 +694,255 @@ describe("SSI agent page", () => {
});
});

describe("Scan: recovery", () => {
const dispatchMock = jest.fn();
const initialState = {
stateCache: {
routes: [],
authentication: {
loggedIn: true,
time: Date.now(),
passcodeIsSet: true,
recoveryWalletProgress: true,
},
},
seedPhraseCache: {
seedPhrase: "seedphrase seedphrase",
},
};

const storeMocked = {
...makeTestStore(initialState),
dispatch: dispatchMock,
};

test("SSI boot url with scanner", async () => {
const barcodes = [
{
displayValue: bootUrl,
format: BarcodeFormat.QrCode,
rawValue: bootUrl,
valueType: BarcodeValueType.Url,
},
];

addListener.mockImplementation(
(
eventName: string,
listenerFunc: (result: BarcodesScannedEvent) => void
) => {
setTimeout(() => {
listenerFunc({
barcodes,
});
}, 100);

return {
remove: jest.fn(),
};
}
);

discoverConnectUrlMock.mockImplementation(() =>
Promise.resolve(connectUrl)
);

const history = createMemoryHistory();
const { getByText, queryByText } = render(
<IonReactMemoryRouter history={history}>
<Provider store={storeMocked}>
<CreateSSIAgent />
</Provider>
</IonReactMemoryRouter>
);

fireEvent.click(
getByText(EN_TRANSLATIONS.ssiagent.connect.buttons.connected)
);

await waitFor(() => {
expect(
queryByText(
EN_TRANSLATIONS.ssiagent.scanssi.scan.button.advancedsetup
)
).toBe(null);
expect(
getByText(EN_TRANSLATIONS.ssiagent.scanssi.scan.button.entermanual)
).toBeVisible;
});

await waitFor(() => {
expect(recoverKeriaAgentMock).toBeCalledWith(
initialState.seedPhraseCache.seedPhrase.split(" "),
connectUrl
);
});
});

test("SSI boot url with manual modal", async () => {
addListener.mockImplementation(
(
eventName: string,
listenerFunc: (result: BarcodesScannedEvent) => void
) => {
return {
remove: jest.fn(),
};
}
);

discoverConnectUrlMock.mockImplementation(() =>
Promise.resolve(connectUrl)
);

const history = createMemoryHistory();
const { getByText, getByTestId } = render(
<IonReactMemoryRouter history={history}>
<Provider store={storeMocked}>
<CreateSSIAgent />
</Provider>
</IonReactMemoryRouter>
);

fireEvent.click(
getByText(EN_TRANSLATIONS.ssiagent.connect.buttons.connected)
);

await waitFor(() => {
expect(
getByText(EN_TRANSLATIONS.ssiagent.scanssi.scan.button.entermanual)
).toBeVisible();
});

fireEvent.click(
getByText(EN_TRANSLATIONS.ssiagent.scanssi.scan.button.entermanual)
);

await waitFor(() => {
expect(getByTestId("ssi-agent-scan-input-modal")).toBeVisible();
});

fireEvent(
getByTestId("ssi-agent-scan-input"),
new CustomEvent("ionInput", {
detail: {
value: bootUrl,
},
})
);

fireEvent.click(
getByText(EN_TRANSLATIONS.ssiagent.scanssi.scan.modal.confirm)
);

await waitFor(() => {
expect(recoverKeriaAgentMock).toBeCalledWith(
initialState.seedPhraseCache.seedPhrase.split(" "),
connectUrl
);
});
});

test("recovery with input url when failed to search connect url", async () => {
addListener.mockImplementation(
(
eventName: string,
listenerFunc: (result: BarcodesScannedEvent) => void
) => {
setTimeout(() => {
listenerFunc({
barcodes,
});
}, 100);

return {
remove: jest.fn(),
};
}
);

discoverConnectUrlMock.mockImplementation(() => {
return Promise.reject(new Error(Agent.CONNECT_URL_DISCOVERY_FAILED));
});

const history = createMemoryHistory();

const { getByText } = render(
<IonReactMemoryRouter history={history}>
<Provider store={storeMocked}>
<CreateSSIAgent />
</Provider>
</IonReactMemoryRouter>
);

fireEvent.click(
getByText(EN_TRANSLATIONS.ssiagent.connect.buttons.connected)
);

await waitFor(() => {
expect(
getByText(EN_TRANSLATIONS.ssiagent.scanssi.scan.button.entermanual)
).toBeVisible();
});

await waitFor(() => {
expect(recoverKeriaAgentMock).toBeCalledWith(
initialState.seedPhraseCache.seedPhrase.split(" "),
bootUrl
);
});
});

test("Show a toast error when the input url isn't boot and connect url", async () => {
addListener.mockImplementation(
(
eventName: string,
listenerFunc: (result: BarcodesScannedEvent) => void
) => {
setTimeout(() => {
listenerFunc({
barcodes,
});
}, 100);

return {
remove: jest.fn(),
};
}
);

discoverConnectUrlMock.mockImplementation(() => {
return Promise.reject(new Error("error"));
});

const history = createMemoryHistory();

const { getByText } = render(
<IonReactMemoryRouter history={history}>
<Provider store={storeMocked}>
<CreateSSIAgent />
</Provider>
</IonReactMemoryRouter>
);

fireEvent.click(
getByText(EN_TRANSLATIONS.ssiagent.connect.buttons.connected)
);

await waitFor(() => {
expect(
getByText(EN_TRANSLATIONS.ssiagent.scanssi.scan.button.entermanual)
).toBeVisible();
});

await waitFor(() => {
expect(dispatchMock).toBeCalledWith(
setToastMsg(ToastMsgType.INVALID_CONNECT_URL)
);
});
});
});

describe("Advanced settings", () => {
async function inputValue(
getByTestId: RenderResult["getByTestId"],
Expand Down Expand Up @@ -778,7 +1034,9 @@ describe("SSI agent page", () => {
});

expect(
getByText(EN_TRANSLATIONS.ssiagent.advancedsetup.description)
getByText(
EN_TRANSLATIONS.ssiagent.advancedsetup.description.connectboot
)
).toBeVisible();

expect(
Expand Down Expand Up @@ -1188,6 +1446,8 @@ describe("SSI agent page", () => {
Promise.reject(new Error(Agent.KERIA_BOOT_FAILED_BAD_NETWORK))
);

discoverConnectUrlMock.mockClear();

const history = createMemoryHistory();

const { getByText, getByTestId } = render(
Expand Down
Loading