Skip to content

Commit

Permalink
fix(SmartCameraWeb): add image test, show an error message when test …
Browse files Browse the repository at this point in the history
…fails (#120)

* fix: count colors in images, and show an error message

* build: add correct version

* fix: fix lint errors

* redesign: use `enable-image-tests` to configure tests

* workflows: deploy files and not folders for smart-camera-web

* lint: remove global rule and disable-next-line for no-bitwise

* redesign: test by default, do not test on `disable-image-tests` attribute

* tests: disable-image-tests on default test files

* docs: update version in README.md

* redesign: change error message for image tests

* tests: add test for image-tests functionality

* refactor: make hasMoreThanNColors a top level function

* fix: fix lint errors

* refactor: address PR feedback, use dedicated screen for failed-image-test

* redesign: add image, copy for failed image test screen

* copy: update failed-image-test copy

* assets: change icon for failed-image-test

* version: bump embed version

* tests: disable image tests for smart-camera-web
tamssokari authored Nov 3, 2023
1 parent c19f1e9 commit 974ecba
Showing 16 changed files with 220 additions and 25 deletions.
2 changes: 1 addition & 1 deletion packages/components/README.md
Original file line number Diff line number Diff line change
@@ -52,7 +52,7 @@ import '@smile_identity/smart-camera-web'
For instance:

```html
<script src="https://cdn.smileidentity.com/js/v1.0.1/smart-camera-web.js"></script>
<script src="https://cdn.smileidentity.com/js/v1.0.2/smart-camera-web.js"></script>
```

### Usage
51 changes: 51 additions & 0 deletions packages/components/cypress/e2e/image-tests.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// smart-camera-web.spec.js created with Cypress
//
// Start writing your Cypress tests below!
// If you're unfamiliar with how Cypress works,
// check out the link below and learn how to write your first test:
// https://on.cypress.io/writing-first-test
context('SmartCameraWeb - Image Tests', () => {
beforeEach(() => {
cy.visit('/image-tests');
});

it('should show an error message when image is unusable', () => {
cy
.get('smart-camera-web')
.shadow()
.find('#request-camera-access')
.click();

cy
.get('smart-camera-web')
.shadow()
.find('#start-image-capture')
.click();

cy
.wait(8000);

cy
.get('smart-camera-web')
.shadow()
.find('#camera-screen')
.should('not.be.visible');

cy
.get('smart-camera-web')
.shadow()
.find('#review-screen')
.should('not.be.visible');

cy
.get('smart-camera-web')
.shadow()
.find('#failed-image-test-screen')
.should('be.visible');

cy.get('smart-camera-web')
.shadow()
.find('#failed-image-test-screen p')
.should('contain.text', 'Device not supported');
});
});
Original file line number Diff line number Diff line change
@@ -28,6 +28,7 @@
<smart-camera-web
capture-id='back'
hide-attribution
disable-image-tests
>
</smart-camera-web>

Original file line number Diff line number Diff line change
@@ -51,7 +51,7 @@
</head>

<body>
<smart-camera-web capture-id="back" show-navigation>
<smart-camera-web capture-id="back" disable-image-tests show-navigation>
</smart-camera-web>

<script src='./instrumented/smart-camera-web.js'></script>
Original file line number Diff line number Diff line change
@@ -28,6 +28,7 @@
<smart-camera-web
capture-id="back"
document-type="GREEN_BOOK"
disable-image-tests
>
</smart-camera-web>

1 change: 1 addition & 0 deletions packages/components/cypress/pages/capture-back-of-id.html
Original file line number Diff line number Diff line change
@@ -27,6 +27,7 @@
<body>
<smart-camera-web
capture-id='back'
disable-image-tests
>
</smart-camera-web>

Original file line number Diff line number Diff line change
@@ -28,6 +28,7 @@
<smart-camera-web
capture-id='true'
hide-back-to-host
disable-image-tests
>
</smart-camera-web>

1 change: 1 addition & 0 deletions packages/components/cypress/pages/capture-id-portrait.html
Original file line number Diff line number Diff line change
@@ -28,6 +28,7 @@
<smart-camera-web
capture-id="true"
document-type="GREEN_BOOK"
disable-image-tests
>
</smart-camera-web>

1 change: 1 addition & 0 deletions packages/components/cypress/pages/capture-id.html
Original file line number Diff line number Diff line change
@@ -27,6 +27,7 @@
<body>
<smart-camera-web
capture-id='true'
disable-image-tests
>
</smart-camera-web>

1 change: 1 addition & 0 deletions packages/components/cypress/pages/document-upload.html
Original file line number Diff line number Diff line change
@@ -27,6 +27,7 @@
<body>
<smart-camera-web
capture-id='back'
disable-image-tests
>
</smart-camera-web>

73 changes: 73 additions & 0 deletions packages/components/cypress/pages/image-tests.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<!doctype html>
<html lang='en'>
<head>
<meta name='viewport' content='width=device-width, initial-scale=1' />
<style>
*,
*::before,
*::after {
box-sizing: border-box;
}

body {
max-width: 100%;
min-height: 100%;
}
button[data-type='icon'] {
align-items: center;
background-color: transparent;
border: 0;
cursor: pointer;
display: flex;
padding: 0;
}
.justify-right {
justify-content: end !important;
}

.nav {
display: flex;
justify-content: space-between;
}

.back-button {
display: block !important;
}

.back-button-text {
font-size: 11px;
line-height: 11px;
color: #3886F7;
}

smart-camera-web {
margin-left: auto;
margin-right: auto;
max-width: 40ch;
padding: 1rem;
width: auto;
}
</style>
</head>

<body>
<smart-camera-web show-navigation>
</smart-camera-web>

<script src='./instrumented/smart-camera-web.js'></script>
<script>
const app = document.querySelector('smart-camera-web');
app.addEventListener('imagesComputed', async (e) => {
console.log(e.detail);
});

app.addEventListener('backExit', async (e) => {
location.href = '/back_pressed'
})

app.addEventListener('close', async (e) => {
location.href = '/closed'
})
</script>
</body>
</html>
2 changes: 1 addition & 1 deletion packages/components/cypress/pages/index.html
Original file line number Diff line number Diff line change
@@ -51,7 +51,7 @@
</head>

<body>
<smart-camera-web show-navigation>
<smart-camera-web disable-image-tests show-navigation>
</smart-camera-web>

<script src='./instrumented/smart-camera-web.js'></script>
2 changes: 1 addition & 1 deletion packages/components/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@smile_identity/smart-camera-web",
"version": "1.0.1",
"version": "1.0.2",
"description": "WebComponent for smartly capturing images on the web, for use with SmileIdentity",
"main": "smart-camera-web.js",
"scripts": {
98 changes: 78 additions & 20 deletions packages/components/smart-camera-web.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const VERSION = '1.0.0-beta.23';
const VERSION = '1.0.2';
const DEFAULT_NO_OF_LIVENESS_FRAMES = 8;
const PORTRAIT_ID_PREVIEW_WIDTH = 396;
const PORTRAIT_ID_PREVIEW_HEIGHT = 527;
@@ -695,6 +695,28 @@ function scwTemplateString() {
</div>
</div>
<div hidden id='failed-image-test-screen' class='flow center'>
<div class='section | flow center'>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" style="enable-background:new 0 0 319 443" height="200" viewBox="0 0 319 443">
<image xlink:href="data:image/png;base64,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" width="319" height="443" style="overflow:visible"/>
</svg>
<p class='color-red | center font-size-large'>
Device not supported
</p>
<p class='center'>
We are unable to use images captured on this device.
</p>
<p class='center'>
Please try using a different device.
</p>
${this.hideAttribution ? '' : `
<powered-by-smile-id></powered-by-smile-id>
`}
</div>
</div>
<div hidden id='review-screen' class='flow center'>
${this.showNavigation ? `
<div class="nav justify-right">
@@ -1185,7 +1207,20 @@ class PoweredBySmileId extends HTMLElement {
}
}

function hasMoreThanNColors(data, n = 16) {
const colors = new Set();
for (let i = 0; i < Math.min(data.length, 10000); i += 4) {
// eslint-disable-next-line no-bitwise
colors.add((data[i] << 16) | (data[i + 1] << 8) | data[i + 2]);
if (colors.size > n) {
return true;
}
}
return false;
}

window.customElements.define('powered-by-smile-id', PoweredBySmileId);

class SmartCameraWeb extends HTMLElement {
constructor() {
super();
@@ -1247,6 +1282,7 @@ class SmartCameraWeb extends HTMLElement {
this.requestScreen = this.shadowRoot.querySelector('#request-screen');
this.activeScreen = this.requestScreen;
this.cameraScreen = this.shadowRoot.querySelector('#camera-screen');
this.failedImageTestScreen = this.shadowRoot.querySelector('#failed-image-test-screen');
this.reviewScreen = this.shadowRoot.querySelector('#review-screen');
this.idEntryScreen = this.shadowRoot.querySelector('#id-entry-screen');
this.IDCameraScreen = this.shadowRoot.querySelector('#id-camera-screen');
@@ -1564,7 +1600,8 @@ class SmartCameraWeb extends HTMLElement {
}
}

_drawImage(canvas, video = this._video) {
_drawImage(canvas, enableImageTests = true, video = this._video) {
this.resetErrorMessage();
const context = canvas.getContext('2d');

context.drawImage(
@@ -1579,15 +1616,27 @@ class SmartCameraWeb extends HTMLElement {
canvas.height,
);

return context;
if (enableImageTests) {
const imageData = context.getImageData(0, 0, canvas.width, canvas.height);

const hasEnoughColors = hasMoreThanNColors(imageData.data);

if (hasEnoughColors) {
return context;
}
throw new Error('Unable to capture webcam images - Please try another device');
} else {
return context;
}
}

_capturePOLPhoto() {
const canvas = document.createElement('canvas');
canvas.width = 240;
canvas.height = (canvas.width * this._video.videoHeight) / this._video.videoWidth;

this._drawImage(canvas);
// NOTE: we do not want to test POL images
this._drawImage(canvas, false);

this._rawImages.push(canvas.toDataURL('image/jpeg'));
}
@@ -1597,7 +1646,8 @@ class SmartCameraWeb extends HTMLElement {
canvas.width = 480;
canvas.height = (canvas.width * this._video.videoHeight) / this._video.videoWidth;

this._drawImage(canvas);
// NOTE: we want to test the image quality of the reference photo
this._drawImage(canvas, !this.disableImageTests);

const image = canvas.toDataURL('image/jpeg');

@@ -1707,27 +1757,31 @@ class SmartCameraWeb extends HTMLElement {
}

_stopVideoStream(stream) {
clearTimeout(this._videoStreamTimeout);
clearInterval(this._imageCaptureInterval);
clearInterval(this._drawingInterval);
this.smileCTA.style.animation = 'none';
try {
clearTimeout(this._videoStreamTimeout);
clearInterval(this._imageCaptureInterval);
clearInterval(this._drawingInterval);
this.smileCTA.style.animation = 'none';

this._capturePOLPhoto(); // NOTE: capture the last photo
this._captureReferencePhoto();
stream.getTracks().forEach((track) => track.stop());
this._capturePOLPhoto(); // NOTE: capture the last photo
this._captureReferencePhoto();
stream.getTracks().forEach((track) => track.stop());

this.reviewImage.src = this._referenceImage;
this.reviewImage.src = this._referenceImage;

const totalNoOfFrames = this._rawImages.length;
const totalNoOfFrames = this._rawImages.length;

const livenessFramesIndices = getLivenessFramesIndices(totalNoOfFrames);
const livenessFramesIndices = getLivenessFramesIndices(totalNoOfFrames);

this._data.images = this._data.images.concat(livenessFramesIndices.map((imageIndex) => ({
image: this._rawImages[imageIndex].split(',')[1],
image_type_id: 6,
})));
this._data.images = this._data.images.concat(livenessFramesIndices.map((imageIndex) => ({
image: this._rawImages[imageIndex].split(',')[1],
image_type_id: 6,
})));

this.setActiveScreen(this.reviewScreen);
this.setActiveScreen(this.reviewScreen);
} catch (error) {
this.setActiveScreen(this.failedImageTestScreen);
}
}

_stopIDVideoStream(stream = this._IDStream) {
@@ -1866,6 +1920,10 @@ class SmartCameraWeb extends HTMLElement {
return value.includes('camera') && value.includes('upload');
}

get disableImageTests() {
return this.hasAttribute('disable-image-tests');
}

get doNotUpload() {
return this.getAttribute('document-capture-modes') === 'camera';
}
6 changes: 6 additions & 0 deletions packages/embed/cypress/support/commands.js
Original file line number Diff line number Diff line change
@@ -223,6 +223,12 @@ Cypress.Commands.add("navigateThroughTotpConsentApp", () => {
});

Cypress.Commands.add("navigateThroughCameraScreens", () => {
cy.log("SmartCameraWeb: disable image tests");

cy.getIFrameBody()
.find("smart-camera-web")
.invoke("attr", "disable-image-tests", "true");

cy.log("navigatingThroughCameraScreens");

cy.getIFrameBody()
2 changes: 1 addition & 1 deletion packages/embed/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@smile_identity/web-page",
"version": "v1.2.1",
"version": "v1.2.2",
"description": "Self Hosted Integration for Smile Identity on the Web",
"private": true,
"main": "inline.js",

0 comments on commit 974ecba

Please sign in to comment.