@smileid/web-components 1.0.0-beta → 1.4.2

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.
Files changed (44) hide show
  1. package/README.md +15 -0
  2. package/components/README.md +1 -1
  3. package/components/camera-permission/CameraPermission.js +6 -2
  4. package/components/camera-permission/CameraPermission.stories.js +10 -4
  5. package/components/document/src/DocumentCaptureScreens.js +41 -11
  6. package/components/document/src/DocumentCaptureScreens.stories.js +16 -12
  7. package/components/document/src/README.md +11 -8
  8. package/components/document/src/document-capture/DocumentCapture.js +299 -231
  9. package/components/document/src/document-capture/DocumentCapture.stories.js +9 -2
  10. package/components/document/src/document-capture/README.md +5 -4
  11. package/components/document/src/document-capture-instructions/DocumentCaptureInstructions.js +33 -33
  12. package/components/document/src/document-capture-instructions/DocumentCaptureInstructions.stories.js +8 -1
  13. package/components/document/src/document-capture-review/DocumentCaptureReview.js +15 -31
  14. package/components/document/src/document-capture-review/DocumentCaptureReview.stories.js +12 -2
  15. package/components/document/src/document-capture-review/README.md +3 -3
  16. package/components/end-user-consent/src/EndUserConsent.js +14 -31
  17. package/components/end-user-consent/src/EndUserConsent.stories.js +8 -2
  18. package/components/navigation/src/Navigation.js +10 -2
  19. package/components/selfie/README.md +28 -4
  20. package/components/selfie/src/SelfieCaptureScreens.js +36 -10
  21. package/components/selfie/src/SelfieCaptureScreens.stories.js +13 -4
  22. package/components/selfie/src/selfie-capture/SelfieCapture.js +95 -23
  23. package/components/selfie/src/selfie-capture/SelfieCapture.stories.js +14 -1
  24. package/components/selfie/src/selfie-capture-instructions/SelfieCaptureInstructions.js +50 -44
  25. package/components/selfie/src/selfie-capture-instructions/SelfieCaptureInstructions.stories.js +8 -2
  26. package/components/selfie/src/selfie-capture-review/SelfieCaptureReview.js +3 -4
  27. package/components/selfie/src/selfie-capture-review/SelfieCaptureReview.stories.js +8 -1
  28. package/components/signature-pad/package-lock.json +3009 -0
  29. package/components/signature-pad/package.json +6 -6
  30. package/components/signature-pad/src/SignaturePad.js +5 -1
  31. package/components/signature-pad/src/SignaturePad.stories.js +10 -2
  32. package/components/smart-camera-web/src/README.md +207 -0
  33. package/components/smart-camera-web/src/SmartCameraWeb.js +56 -7
  34. package/components/smart-camera-web/src/SmartCameraWeb.stories.js +27 -7
  35. package/components/totp-consent/src/TotpConsent.js +15 -3
  36. package/cypress/e2e/smart-camera-web-agent-mode.cy.js +144 -0
  37. package/cypress/e2e/smart-camera-web-complete-flow.cy.js +221 -0
  38. package/cypress/e2e/smart-camera-web.cy.js +1 -1
  39. package/cypress/pages/smart-camera-web-agent-mode.html +36 -0
  40. package/cypress/pages/smart-camera-web-complete-flow.html +42 -0
  41. package/cypress/pages/smart-camera-web.html +1 -1
  42. package/domain/camera/src/SmartCamera.js +28 -0
  43. package/package.json +8 -8
  44. package/styles/src/styles.js +14 -3
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smileid/signature-pad",
3
- "version": "1.0.0",
3
+ "version": "1.4.2",
4
4
  "private": "true",
5
5
  "exports": {
6
6
  ".": "./index.js"
@@ -15,16 +15,16 @@
15
15
  ],
16
16
  "author": "SmileID <support@usesmileid.com> (https://usesmileid.com)",
17
17
  "dependencies": {
18
- "signature_pad": "^4.1.7"
18
+ "signature_pad": "^5.0.2"
19
19
  },
20
20
  "devDependencies": {
21
21
  "eslint": "^8.57.0",
22
22
  "eslint-config-airbnb-base": "^15.0.0",
23
23
  "eslint-config-prettier": "^9.1.0",
24
- "eslint-plugin-cypress": "^2.15.1",
24
+ "eslint-plugin-cypress": "^3.3.0",
25
25
  "eslint-plugin-import": "^2.29.1",
26
- "eslint-plugin-jest": "^28.2.0",
27
- "eslint-plugin-prettier": "^5.1.3",
28
- "prettier": "^3.2.2"
26
+ "eslint-plugin-jest": "^28.6.0",
27
+ "eslint-plugin-prettier": "^5.2.1",
28
+ "prettier": "^3.3.3"
29
29
  }
30
30
  }
@@ -177,7 +177,7 @@ button[data-variant="text"] {
177
177
  }
178
178
 
179
179
  button[data-variant="solid"] {
180
- --button-color: var(--color-default);
180
+ --button-color: ${this.themeColor};
181
181
  border-radius: 2.5rem;
182
182
  border: 0;
183
183
  background-color: transparent;
@@ -468,6 +468,10 @@ button:disabled {
468
468
  get allowUpload() {
469
469
  return this.hasAttribute('allow-upload');
470
470
  }
471
+
472
+ get themeColor() {
473
+ return this.getAttribute('theme-color') || '#001096';
474
+ }
471
475
  }
472
476
 
473
477
  if ('customElements' in window) {
@@ -1,23 +1,31 @@
1
1
  import './SignaturePad';
2
2
 
3
3
  const meta = {
4
+ args: {
5
+ 'theme-color': '#001096',
6
+ },
7
+ argTypes: {
8
+ 'theme-color': { control: 'color' },
9
+ },
4
10
  component: 'smileid-signature-pad',
5
11
  };
6
12
 
7
13
  export default meta;
8
14
 
9
15
  export const SignaturePad = {
10
- render: () => `
16
+ render: (args) => `
11
17
  <smileid-signature-pad
18
+ theme-color='${args['theme-color']}'
12
19
  >
13
20
  </smileid-signature-pad>
14
21
  `,
15
22
  };
16
23
 
17
24
  export const SignaturePadWithUploads = {
18
- render: () => `
25
+ render: (args) => `
19
26
  <smileid-signature-pad
20
27
  allow-upload
28
+ theme-color='${args['theme-color']}'
21
29
  >
22
30
  </smileid-signature-pad>
23
31
  `,
@@ -0,0 +1,207 @@
1
+ # SmartCameraWeb
2
+
3
+ `SmartCameraWeb` is a [Web Component](https://developer.mozilla.org/en-US/docs/Web/Web_Components) designed to capture images including selfies, liveness images, and ID Document images for use with SmileIdentity. It interfaces with the [Server to Server](https://docs.usesmileid.com/server-to-server) libraries, serving as a user interface client.
4
+
5
+ Explore an [example full stack integration](https://glitch.com/edit/#!/smart-camera-web-demo-node) using our [NodeJS](https://docs.usesmileid.com/server-to-server/javascript) library.
6
+
7
+ ## Getting Started
8
+
9
+ To integrate `SmartCameraWeb`, follow these steps:
10
+
11
+ - [SmartCameraWeb](#smartcameraweb)
12
+ - [Getting Started](#getting-started)
13
+ - [Choose a Server to Server Library](#choose-a-server-to-server-library)
14
+ - [Installation](#installation)
15
+ - [Install Via NPM](#install-via-npm)
16
+ - [Usage](#usage)
17
+ - [Compatibility](#compatibility)
18
+ - [Support](#support)
19
+ - [Development](#development)
20
+
21
+ ### Choose a Server to Server Library
22
+
23
+ Supported [Server to Server Libraries](https://docs.usesmileid.com/server-to-server) include:
24
+
25
+ - [Java](https://docs.usesmileid.com/server-to-server/java)
26
+ - [NodeJS](https://docs.usesmileid.com/server-to-server/javascript)
27
+ - [PHP](https://docs.usesmileid.com/server-to-server/php)
28
+ - [Python](https://docs.usesmileid.com/server-to-server/python)
29
+ - [Ruby](https://docs.usesmileid.com/server-to-server/ruby)
30
+
31
+ > **Note**: Code samples in this documentation utilize the NodeJS Server to Server library.
32
+
33
+ ### Installation
34
+
35
+ You can install via NPM or directly include it from our CDN.
36
+
37
+ #### Install Via NPM
38
+
39
+ ```shell
40
+ npm install @smileid/web-components@<version>
41
+ ```
42
+
43
+ Then, in your VueJS, AngularJS, or React component:
44
+
45
+ ```js
46
+ import '@smileid/web-components/smart-camera-web';
47
+ ```
48
+
49
+ ### Usage
50
+
51
+ After installation and necessary imports:
52
+
53
+ 1. Add the desired markup to your page/component:
54
+
55
+ - **For Selfie Capture / Liveness Images**:
56
+
57
+ ```html
58
+ <smart-camera-web></smart-camera-web>
59
+ ```
60
+
61
+ - **For Selfie Capture / Liveness and ID Images**:
62
+
63
+ ```html
64
+ <smart-camera-web capture-id></smart-camera-web>
65
+ ```
66
+
67
+ Initially, you'll see this image:
68
+ ![Selfie Capture Instruction](https://cdn.smileidentity.com/images/smart-camera-web/selfie-capture-instruction.png)
69
+
70
+ After granting access, the capture screen appears:
71
+ ![Selfie Camera](https://cdn.smileidentity.com/images/smart-camera-web/selfie-capture.png)
72
+
73
+ Upon capturing a selfie, you'll reach the review screen:
74
+ ![Selfie Review](https://cdn.smileidentity.com/images/smart-camera-web/selfie-capture-review.png)
75
+
76
+ ![Document Capture Instruction](https://cdn.smileidentity.com/images/smart-camera-web/document-capture-instruction.png)
77
+
78
+ If the `capture-id` attribute is used, additional screens include:
79
+
80
+ ![ID Camera](https://cdn.smileidentity.com/images/smart-camera-web/document-capture.png)
81
+
82
+ ![ID Review](https://cdn.smileidentity.com/images/smart-camera-web/document-review-new.png)
83
+
84
+ 2. Handle the `smart-camera-web.publish` event:
85
+
86
+ When the user approves the captured image, an `smart-camera-web.publish` event is dispatched. The event returns a [CustomEvent](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent) payload in `e.detail`.
87
+
88
+ Here's a script example to handle the event and send data to a backend endpoint:
89
+
90
+ ```html
91
+ <script>
92
+ const app = document.querySelector('smart-camera-web');
93
+
94
+ const postContent = async (data) => {
95
+ const options = {
96
+ method: 'POST',
97
+ headers: {
98
+ 'Content-Type': 'application/json',
99
+ },
100
+ body: JSON.stringify(data),
101
+ };
102
+
103
+ try {
104
+ const response = await fetch('/', options);
105
+ const json = await response.json();
106
+
107
+ return json;
108
+ } catch (e) {
109
+ throw e;
110
+ }
111
+ };
112
+
113
+ app.addEventListener('smart-camera-web.publish', async (e) => {
114
+ try {
115
+ const response = await postContent(e.detail);
116
+
117
+ console.log(response);
118
+ } catch (e) {
119
+ console.error(e);
120
+ }
121
+ });
122
+ </script>
123
+ ```
124
+
125
+ The provided backend endpoint uses the NodeJS Server to Server library and ExpressJS:
126
+
127
+ ```js
128
+ const express = require('express');
129
+ const { v4: UUID } = require('uuid');
130
+
131
+ if (process.env.NODE_ENV === 'development') {
132
+ const dotenv = require('dotenv');
133
+
134
+ dotenv.config();
135
+ }
136
+
137
+ const SIDCore = require('smile-identity-core');
138
+ const SIDSignature = SIDCore.Signature;
139
+ const SIDWebAPI = SIDCore.WebApi;
140
+
141
+ const app = express();
142
+
143
+ app.use(express.json({ limit: '500kb' }));
144
+ app.use(express.static('public'));
145
+
146
+ app.post('/', async (req, res, next) => {
147
+ try {
148
+ const { PARTNER_ID, API_KEY, SID_SERVER } = process.env;
149
+ const connection = new SIDWebAPI(
150
+ PARTNER_ID,
151
+ '/callback',
152
+ API_KEY,
153
+ SID_SERVER,
154
+ );
155
+
156
+ const partner_params_from_server = {
157
+ user_id: `user-${UUID()}`,
158
+ job_id: `job-${UUID()}`,
159
+ job_type: 4, // job_type is the simplest job we have which enrolls a user using their selfie
160
+ };
161
+
162
+ const {
163
+ images,
164
+ partner_params: { libraryVersion },
165
+ } = req.body;
166
+
167
+ const options = {
168
+ return_job_status: true,
169
+ };
170
+
171
+ const partner_params = Object.assign({}, partner_params_from_server, {
172
+ libraryVersion,
173
+ });
174
+
175
+ const result = await connection.submit_job(
176
+ partner_params,
177
+ images,
178
+ {},
179
+ options,
180
+ );
181
+
182
+ res.json(result);
183
+ } catch (e) {
184
+ console.error(e);
185
+ }
186
+ });
187
+
188
+ // NOTE: This can be used to process responses. don't forget to add it as a callback option in the `connection` config on L22
189
+ // https://docs.usesmileid.com/further-reading/faqs/how-do-i-setup-a-callback
190
+ app.post('/callback', (req, res, next) => {});
191
+
192
+ app.listen(process.env.PORT || 4000);
193
+ ```
194
+
195
+ This approach can also be achieved using other Server to Server libraries.
196
+
197
+ ## Compatibility
198
+
199
+ `SmartCameraWeb` is compatible with most JavaScript frameworks and libraries. For integration with [ReactJS](https://reactjs.org), refer to this [tutorial](https://www.robinwieruch.de/react-web-components) due to React-WebComponents compatibility issues.
200
+
201
+ ## Support
202
+
203
+ Tested on the latest versions of Chrome, Edge, Firefox, and Safari. If compatibility issues arise on certain browsers, please notify us.
204
+
205
+ ## Development
206
+
207
+ Note: `smart-camera-web.js` is generated from `src/` using [esbuild](https://esbuild.github.io/). To make changes, edit the source files and run `npm run build` to generate the new `smart-camera-web.js` file.
@@ -9,13 +9,14 @@ import { version as COMPONENTS_VERSION } from '../../../package.json';
9
9
 
10
10
  function scwTemplateString() {
11
11
  return `
12
- ${styles}
12
+ ${styles(this.themeColor)}
13
13
  <div>
14
- <camera-permission ${this.title} ${this.showNavigation} ${this.hideInstructions ? '' : 'hidden'}></camera-permission>
15
- <selfie-capture-screens ${this.title} ${this.showNavigation} ${this.disableImageTests} ${this.hideAttribution} ${this.hideInstructions} hidden
16
- ${this.hideBackToHost}
14
+ <camera-permission ${this.applyComponentThemeColor} ${this.title} ${this.showNavigation} ${this.hideInstructions ? '' : 'hidden'} ${this.hideAttribution}></camera-permission>
15
+ <selfie-capture-screens ${this.applyComponentThemeColor} ${this.title} ${this.showNavigation} ${this.disableImageTests} ${this.hideAttribution} ${this.hideInstructions} hidden
16
+ ${this.hideBackToHost} ${this.allowAgentMode} ${this.allowAgentModeTests}
17
17
  ></selfie-capture-screens>
18
- <document-capture-screens document-type=${this.documentType} ${this.title} ${this.documentCaptureModes} ${this.showNavigation} ${this.hideAttribution} hidden></document-capture-screens>
18
+ <document-capture-screens ${this.applyComponentThemeColor} document-type=${this.documentType} ${this.title} ${this.documentCaptureModes} ${this.showNavigation} ${this.hideAttribution}
19
+ ${this.hideBackOfId} ${this.applyComponentThemeColor} hidden></document-capture-screens>
19
20
  </div>
20
21
  `;
21
22
  }
@@ -60,19 +61,30 @@ class SmartCameraWeb extends HTMLElement {
60
61
 
61
62
  static get observedAttributes() {
62
63
  return [
64
+ 'allow-agent-mode',
65
+ 'disable-image-tests',
63
66
  'document-capture-modes',
64
67
  'document-type',
68
+ 'hide-attribution',
69
+ 'hide-back-of-id',
65
70
  'hide-back-to-host',
66
71
  'show-navigation',
72
+ 'theme-color',
67
73
  ];
68
74
  }
69
75
 
70
76
  attributeChangedCallback(name) {
71
77
  switch (name) {
78
+ case 'allow-agent-mode':
79
+ case 'disable-image-tests':
72
80
  case 'document-capture-modes':
73
81
  case 'document-type':
82
+ case 'hide-attribution':
83
+ case 'hide-back-of-id':
74
84
  case 'hide-back-to-host':
75
85
  case 'show-navigation':
86
+ case 'theme-color':
87
+ this.disconnectedCallback();
76
88
  this.shadowRoot.innerHTML = this.render();
77
89
  this.setUpEventListeners();
78
90
  break;
@@ -105,7 +117,11 @@ class SmartCameraWeb extends HTMLElement {
105
117
  'selfie-capture-screens.publish',
106
118
  (event) => {
107
119
  this._data.images = event.detail.images;
108
- this.setActiveScreen(this.documentCapture);
120
+ if (!this.captureId) {
121
+ this._publishSelectedImages();
122
+ } else {
123
+ this.setActiveScreen(this.documentCapture);
124
+ }
109
125
  },
110
126
  );
111
127
 
@@ -182,6 +198,10 @@ class SmartCameraWeb extends HTMLElement {
182
198
  );
183
199
  }
184
200
 
201
+ get captureId() {
202
+ return this.hasAttribute('capture-id');
203
+ }
204
+
185
205
  get documentType() {
186
206
  return this.getAttribute('document-type');
187
207
  }
@@ -195,7 +215,7 @@ class SmartCameraWeb extends HTMLElement {
195
215
  }
196
216
 
197
217
  get hideBackOfId() {
198
- return this.hasAttribute('hide-back-of-id');
218
+ return this.hasAttribute('hide-back-of-id') ? 'hide-back-of-id' : '';
199
219
  }
200
220
 
201
221
  get showNavigation() {
@@ -206,6 +226,18 @@ class SmartCameraWeb extends HTMLElement {
206
226
  return this.hasAttribute('hide-back-to-host') ? 'hide-back-to-host' : '';
207
227
  }
208
228
 
229
+ get allowAgentMode() {
230
+ return this.hasAttribute('allow-agent-mode')
231
+ ? `allow-agent-mode=${this.getAttribute('allow-agent-mode')}`
232
+ : '';
233
+ }
234
+
235
+ get allowAgentModeTests() {
236
+ return this.hasAttribute('show-agent-mode-for-tests')
237
+ ? 'show-agent-mode-for-tests'
238
+ : '';
239
+ }
240
+
209
241
  get title() {
210
242
  return this.hasAttribute('title')
211
243
  ? `title=${this.getAttribute('title')}`
@@ -228,6 +260,23 @@ class SmartCameraWeb extends HTMLElement {
228
260
  return this.hasAttribute('hide-attribution') ? 'hide-attribution' : '';
229
261
  }
230
262
 
263
+ get hasThemeColor() {
264
+ return (
265
+ this.hasAttribute('theme-color') &&
266
+ ![null, undefined, 'null', 'undefined'].includes(
267
+ this.getAttribute('theme-color'),
268
+ )
269
+ );
270
+ }
271
+
272
+ get themeColor() {
273
+ return this.hasThemeColor ? this.getAttribute('theme-color') : '#001096';
274
+ }
275
+
276
+ get applyComponentThemeColor() {
277
+ return this.hasThemeColor ? `theme-color='${this.themeColor}'` : '';
278
+ }
279
+
231
280
  setActiveScreen(screen) {
232
281
  this.activeScreen?.setAttribute('hidden', '');
233
282
  screen.removeAttribute('hidden');
@@ -1,35 +1,55 @@
1
1
  import './SmartCameraWeb';
2
2
 
3
3
  const meta = {
4
+ args: {
5
+ 'theme-color': '#001096',
6
+ },
7
+ argTypes: {
8
+ 'theme-color': { control: 'color' },
9
+ },
4
10
  component: 'smart-camera-web',
5
11
  };
6
12
 
7
13
  export default meta;
8
14
 
9
15
  export const SmartCameraWeb = {
10
- render: () => `
11
- <smart-camera-web show-navigation>
16
+ render: (args) => `
17
+ <smart-camera-web theme-color='${args['theme-color']}' capture-id show-navigation>
12
18
  </smart-camera-web>
13
19
  `,
14
20
  };
15
21
 
16
22
  export const SmartCameraWebWithOutInstructions = {
17
- render: () => `
18
- <smart-camera-web hide-instructions>
23
+ render: (args) => `
24
+ <smart-camera-web theme-color='${args['theme-color']}' capture-id hide-instructions>
19
25
  </smart-camera-web>
20
26
  `,
21
27
  };
22
28
 
23
29
  export const SmartCameraWebWithOutNavigation = {
24
- render: () => `
25
- <smart-camera-web>
30
+ render: (args) => `
31
+ <smart-camera-web theme-color='${args['theme-color']}' capture-id>
26
32
  </smart-camera-web>
27
33
  `,
28
34
  };
29
35
 
30
36
  export const SmartCameraWebWithOutBackToHost = {
37
+ render: (args) => `
38
+ <smart-camera-web theme-color='${args['theme-color']}' capture-id show-navigation hide-back-to-host>
39
+ </smart-camera-web>
40
+ `,
41
+ };
42
+
43
+ export const SmartCameraWebWithOutBackId = {
44
+ render: (args) => `
45
+ <smart-camera-web theme-color='${args['theme-color']}' capture-id show-navigation hide-back-of-id>
46
+ </smart-camera-web>
47
+ `,
48
+ };
49
+
50
+ export const SmartCameraWebAgentMode = {
31
51
  render: () => `
32
- <smart-camera-web show-navigation hide-back-to-host>
52
+ <smart-camera-web hide-instructions hide-back-of-id allow-agent-mode='true' show-agent-mode-for-tests>
33
53
  </smart-camera-web>
34
54
  `,
35
55
  };
@@ -196,7 +196,7 @@ function markup() {
196
196
  .back-button-text {
197
197
  font-size: 11px;
198
198
  line-height: 11px;
199
- color: rgb(21, 31, 114);
199
+ color: ${this.themeColor || 'rgb(21, 31, 114)'};
200
200
  }
201
201
 
202
202
  #error,
@@ -290,7 +290,7 @@ function markup() {
290
290
  <button type='button' data-type='icon' id="back-button" class="back-button">
291
291
  <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none">
292
292
  <path fill="#DBDBC4" d="M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10Z" opacity=".4"/>
293
- <path fill="#001096" d="M15.5 11.25h-5.19l1.72-1.72c.29-.29.29-.77 0-1.06a.754.754 0 0 0-1.06 0l-3 3c-.29.29-.29.77 0 1.06l3 3c.15.15.34.22.53.22s.38-.07.53-.22c.29-.29.29-.77 0-1.06l-1.72-1.72h5.19c.41 0 .75-.34.75-.75s-.34-.75-.75-.75Z"/>
293
+ <path fill="${this.themeColor}" d="M15.5 11.25h-5.19l1.72-1.72c.29-.29.29-.77 0-1.06a.754.754 0 0 0-1.06 0l-3 3c-.29.29-.29.77 0 1.06l3 3c.15.15.34.22.53.22s.38-.07.53-.22c.29-.29.29-.77 0-1.06l-1.72-1.72h5.19c.41 0 .75-.34.75-.75s-.34-.75-.75-.75Z"/>
294
294
  </svg>
295
295
  </button>
296
296
  <div class="back-button-text">Back</div>
@@ -337,7 +337,7 @@ function markup() {
337
337
  <button type='button' data-type='icon' id="back-to-entry-button" class="back-button">
338
338
  <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none">
339
339
  <path fill="#DBDBC4" d="M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10Z" opacity=".4"/>
340
- <path fill="#001096" d="M15.5 11.25h-5.19l1.72-1.72c.29-.29.29-.77 0-1.06a.754.754 0 0 0-1.06 0l-3 3c-.29.29-.29.77 0 1.06l3 3c.15.15.34.22.53.22s.38-.07.53-.22c.29-.29.29-.77 0-1.06l-1.72-1.72h5.19c.41 0 .75-.34.75-.75s-.34-.75-.75-.75Z"/>
340
+ <path fill="${this.themeColor}" d="M15.5 11.25h-5.19l1.72-1.72c.29-.29.29-.77 0-1.06a.754.754 0 0 0-1.06 0l-3 3c-.29.29-.29.77 0 1.06l3 3c.15.15.34.22.53.22s.38-.07.53-.22c.29-.29.29-.77 0-1.06l-1.72-1.72h5.19c.41 0 .75-.34.75-.75s-.34-.75-.75-.75Z"/>
341
341
  </svg>
342
342
  </button>
343
343
  <div class="back-button-text">Back</div>
@@ -893,6 +893,18 @@ class TotpConsent extends HTMLElement {
893
893
  return this.getAttribute('token');
894
894
  }
895
895
 
896
+ get themeColor() {
897
+ return this.getAttribute('theme-color') || '#001096';
898
+ }
899
+
900
+ get hideBack() {
901
+ return this.hasAttribute('hide-back');
902
+ }
903
+
904
+ get showNavigation() {
905
+ return this.hasAttribute('show-navigation');
906
+ }
907
+
896
908
  handleTotpConsentGrant() {
897
909
  const customEvent = new CustomEvent('end-user-consent.totp.granted', {
898
910
  detail: {
@@ -0,0 +1,144 @@
1
+ context('SmartCameraWeb', () => {
2
+ beforeEach(() => {
3
+ cy.visit('/smart-camera-web-agent-mode');
4
+ });
5
+
6
+ it('should switch from the selfie mode to agent mode"', () => {
7
+ cy.log('Enable agent mode for tests');
8
+ cy.get('smart-camera-web')
9
+ .invoke('attr', 'allow-agent-mode', 'true')
10
+ .should('have.attr', 'allow-agent-mode', 'true');
11
+
12
+ cy.get('smart-camera-web').invoke(
13
+ 'attr',
14
+ 'show-agent-mode-for-tests',
15
+ 'true',
16
+ );
17
+ cy.get('smart-camera-web').invoke('attr', 'disable-image-tests', '');
18
+
19
+ cy.clock();
20
+ cy.get('smart-camera-web')
21
+ .shadow()
22
+ .find('selfie-capture-instructions')
23
+ .shadow()
24
+ .find('#allow')
25
+ .click();
26
+
27
+ cy.get('smart-camera-web')
28
+ .shadow()
29
+ .find('selfie-capture')
30
+ .should('be.visible');
31
+
32
+ cy.get('smart-camera-web')
33
+ .shadow()
34
+ .find('selfie-capture')
35
+ .shadow()
36
+ .should('contain.text', 'Agent Mode On');
37
+
38
+ cy.get('smart-camera-web')
39
+ .shadow()
40
+ .find('selfie-capture')
41
+ .shadow()
42
+ .find('#switch-camera')
43
+ .click();
44
+
45
+ cy.get('smart-camera-web')
46
+ .shadow()
47
+ .find('selfie-capture')
48
+ .shadow()
49
+ .should('contain.text', 'Agent Mode Off');
50
+
51
+ cy.get('smart-camera-web')
52
+ .shadow()
53
+ .find('selfie-capture')
54
+ .shadow()
55
+ .find('#switch-camera')
56
+ .click();
57
+
58
+ cy.get('smart-camera-web')
59
+ .shadow()
60
+ .find('selfie-capture')
61
+ .shadow()
62
+ .should('contain.text', 'Agent Mode On');
63
+
64
+ cy.get('smart-camera-web')
65
+ .shadow()
66
+ .find('selfie-capture')
67
+ .shadow()
68
+ .should('contain.text', 'Take a Selfie');
69
+
70
+ cy.get('smart-camera-web')
71
+ .shadow()
72
+ .find('selfie-capture')
73
+ .shadow()
74
+ .find('#start-image-capture')
75
+ .click();
76
+
77
+ cy.tick(8000);
78
+
79
+ cy.get('smart-camera-web')
80
+ .shadow()
81
+ .find('selfie-capture')
82
+ .shadow()
83
+ .should('not.be.visible');
84
+
85
+ cy.get('smart-camera-web')
86
+ .shadow()
87
+ .find('selfie-capture-review')
88
+ .should('be.visible');
89
+ });
90
+
91
+ it('should not show the agent mode switch button"', () => {
92
+ cy.get('smart-camera-web')
93
+ .shadow()
94
+ .find('selfie-capture')
95
+ .invoke('attr', 'show-agent-mode-for-tests', 'false');
96
+ cy.get('smart-camera-web').invoke('attr', 'disable-image-tests', '');
97
+
98
+ cy.clock();
99
+ cy.get('smart-camera-web')
100
+ .shadow()
101
+ .find('selfie-capture-instructions')
102
+ .shadow()
103
+ .find('#allow')
104
+ .click();
105
+
106
+ cy.get('smart-camera-web')
107
+ .shadow()
108
+ .find('selfie-capture')
109
+ .should('be.visible');
110
+
111
+ cy.get('smart-camera-web')
112
+ .shadow()
113
+ .find('selfie-capture')
114
+ .shadow()
115
+ .find('#switch-camera')
116
+ .should('not.exist');
117
+
118
+ cy.get('smart-camera-web')
119
+ .shadow()
120
+ .find('selfie-capture')
121
+ .shadow()
122
+ .should('contain.text', 'Take a Selfie');
123
+
124
+ cy.get('smart-camera-web')
125
+ .shadow()
126
+ .find('selfie-capture')
127
+ .shadow()
128
+ .find('#start-image-capture')
129
+ .click();
130
+
131
+ cy.tick(8000);
132
+
133
+ cy.get('smart-camera-web')
134
+ .shadow()
135
+ .find('selfie-capture')
136
+ .shadow()
137
+ .should('not.be.visible');
138
+
139
+ cy.get('smart-camera-web')
140
+ .shadow()
141
+ .find('selfie-capture-review')
142
+ .should('be.visible');
143
+ });
144
+ });