├── .eslintrc.json ├── .gitignore ├── .npmignore ├── .npmrc ├── README.md ├── package-lock.json ├── package.json ├── src ├── index.ts ├── styles │ └── style.css ├── template.ts ├── util.ts └── xhr.ts ├── test ├── template.test.ts ├── util.test.ts └── xhr.test.ts ├── tsconfig.json └── webpack └── webpack.config.js /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es6": true 5 | }, 6 | "extends": [ 7 | "eslint:recommended", 8 | "plugin:@typescript-eslint/recommended", 9 | "plugin:@typescript-eslint/eslint-recommended", 10 | "prettier" 11 | ], 12 | "globals": { 13 | "Atomics": "readonly", 14 | "SharedArrayBuffer": "readonly" 15 | }, 16 | "parser": "@typescript-eslint/parser", 17 | "parserOptions": { 18 | "ecmaVersion": 2018, 19 | "sourceType": "module" 20 | }, 21 | "plugins": [ 22 | "@typescript-eslint" 23 | ], 24 | "rules": { 25 | "@typescript-eslint/explicit-function-return-type": "off" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | 3 | .DS_Store 4 | .vscode 5 | .idea 6 | dist 7 | lib 8 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | dist 2 | src 3 | test 4 | node_modules 5 | webpack.config.js 6 | .idea 7 | .DS_Store 8 | .vscode 9 | .npmrc 10 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | engine-strict=true 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | --- 2 | owner: "Client Tools" 3 | description: "JS SDK for easy integration with Veriff" 4 | status: "production" 5 | type: "library" 6 | --- 7 | 8 | # Veriff JS SDK 9 | Veriff JS SDK, is a simple and customisable library which helps to integrate with Veriff Online Identity solution. 10 | 11 | ### Install JS SDK 12 | Include as a script tag: 13 | 14 | ```html 15 | 16 | ``` 17 | 18 | or install it via a package manager 19 | 20 | ```bash 21 | $ npm install --save @veriff/js-sdk 22 | ``` 23 | 24 | ```javascript 25 | // CommonJS 26 | const Veriff = require('@veriff/js-sdk'); 27 | 28 | // ES6 style import 29 | import { Veriff } from '@veriff/js-sdk'; 30 | 31 | ``` 32 | 33 | ### Adding JS SDK 34 | Veriff JS SDK requires one parent element in HTML: 35 | 36 | 37 | ```html 38 |
39 | ``` 40 | 41 | It is possible to set the width of js-sdk form through style attribute: 42 | 43 | ```html 44 |
45 | ``` 46 | 47 | In order to initialize the library, *API Key*, *parentId* and *onSession* callback function is required. 48 | 49 | ```javascript 50 | const veriff = Veriff({ 51 | apiKey: 'API_KEY', 52 | parentId: 'veriff-root', 53 | onSession: function(err, response) { 54 | // received the response, verification can be started now 55 | } 56 | }); 57 | 58 | veriff.mount(); 59 | ``` 60 | 61 | By default the following form will be rendered: 62 | 63 | ![alt text](https://cdn.veriff.me/assets/jssdk-default-sample.png "Veriff JS SDK") 64 | 65 | *onSession* function is executed after the *response* is received from the API, response body contains a verification object with following schema: 66 | 67 | 68 | ```json 69 | { 70 | "status": "success", 71 | "verification": { 72 | "id": "UUID V4 Identifying the verification", 73 | "url": "full url to which a person should be redirected in order to proceed with verification flow", 74 | "host": "hostname", 75 | "status": "status of the verification", 76 | "sessionToken": "JWT encoded verification token" 77 | } 78 | } 79 | ``` 80 | 81 | vendorData: string - Client specific data string, max 1000 characters long, will be sent back unmodified using webhooks. 82 | In case the Given name / Last name / Vendor Data or all of them are known, they can be passed to the SDK, therefore text input fields will not be rendered. 83 | 84 | ```javascript 85 | const veriff = Veriff({ 86 | apiKey: 'API_KEY', 87 | parentId: 'veriff-root', 88 | onSession: function(err, response) { 89 | // received the response, verification can be started now 90 | } 91 | }); 92 | veriff.setParams({ 93 | person: { 94 | givenName: 'Foo', 95 | lastName: 'Bar' 96 | }, 97 | vendorData: '7eb19312-79d6-11ec-90d6-0242ac120003' 98 | }); 99 | veriff.mount({ 100 | submitBtnText: 'Get verified' 101 | }); 102 | ``` 103 | 104 | ![alt text](https://cdn.veriff.me/assets/jssdk-only-button-sample.png "Veriff JS SDK") 105 | 106 | It is possible to disable fields rendering without passing any data by not including anything in corresponding value: 107 | 108 | ```javascript 109 | const veriff = Veriff({ 110 | apiKey: 'API_KEY', 111 | parentId: 'veriff-root', 112 | onSession: function(err, response) { 113 | // received the response, verification can be started now 114 | } 115 | }); 116 | veriff.setParams({ 117 | person: { 118 | givenName: ' ', 119 | lastName: ' ' 120 | }, 121 | vendorData: ' ' 122 | }); 123 | veriff.mount({ 124 | submitBtnText: 'Get verified' 125 | }); 126 | ``` 127 | 128 | Additionally, the input placeholder and button text value can be customised. 129 | 130 | ```javascript 131 | const veriff = Veriff({ 132 | apiKey: 'API_KEY', 133 | parentId: 'veriff-root', 134 | onSession: function(err, response) { 135 | // received the response, verification can be started now 136 | } 137 | }); 138 | veriff.mount({ 139 | formLabel: { 140 | givenName: 'First name', 141 | lastName: 'Family name', 142 | vendorData: 'Data' 143 | }, 144 | submitBtnText: 'Get verified', 145 | loadingText: 'Please wait...' 146 | }); 147 | ``` 148 | ![alt text](https://cdn.veriff.me/assets/jssdk-default-sample.png "Veriff JS SDK") 149 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@veriff/js-sdk", 3 | "version": "1.5.1", 4 | "description": "JavaScript SDK for Veriff identity verification", 5 | "main": "lib/veriff.js", 6 | "types": "lib/index.d.ts", 7 | "scripts": { 8 | "build": "webpack --config webpack/webpack.config.js --mode production", 9 | "dev": "webpack --progress --mode=development --watch --config webpack/webpack.config.js", 10 | "test": "jest", 11 | "format": "prettier --write \"src/**/*.ts\" \"src/**/*.js\"", 12 | "lint": "eslint --ext=js,ts src" 13 | }, 14 | "author": "Ilia Aphtsiauri (https://github.com/iaptsiauri)", 15 | "contributors": [ 16 | "Maksim Kitsigin (https://github.com/fixmk)" 17 | ], 18 | "keywords": [ 19 | "veriff", 20 | "sdk", 21 | "online", 22 | "identity", 23 | "verification" 24 | ], 25 | "jest": { 26 | "roots": [ 27 | "/test" 28 | ], 29 | "transform": { 30 | "^.+\\.(ts|tsx)$": "ts-jest" 31 | }, 32 | "testEnvironment": "jsdom", 33 | "testRegex": "(/__test__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?|ts?)$" 34 | }, 35 | "prettier": { 36 | "printWidth": 120, 37 | "singleQuote": true, 38 | "trailingComma": "es5", 39 | "semi": true, 40 | "bracketSpacing": true, 41 | "arrowParens": "always", 42 | "endOfLine": "lf" 43 | }, 44 | "engines": { 45 | "node": ">=16", 46 | "npm": ">=8" 47 | }, 48 | "license": "ISC", 49 | "devDependencies": { 50 | "@types/jest": "^27.5.0", 51 | "@typescript-eslint/eslint-plugin": "^5.22.0", 52 | "@typescript-eslint/parser": "^5.22.0", 53 | "babel-eslint": "^10.1.0", 54 | "babel-loader": "^8.2.5", 55 | "babel-plugin-add-module-exports": "^1.0.4", 56 | "babel-preset-env": "^1.7.0", 57 | "chai": "^4.3.6", 58 | "css-loader": "^6.7.1", 59 | "eslint": "^8.14.0", 60 | "eslint-config-prettier": "^8.5.0", 61 | "eslint-loader": "^4.0.2", 62 | "jasmine-core": "^4.1.0", 63 | "jest": "^28.0.3", 64 | "jest-environment-jsdom": "^28.0.2", 65 | "prettier": "^2.6.2", 66 | "sinon": "^13.0.2", 67 | "source-map-loader": "^3.0.1", 68 | "style-loader": "^3.3.1", 69 | "ts-jest": "^28.0.1", 70 | "ts-loader": "^9.3.0", 71 | "typescript": "^4.6.4", 72 | "webpack": "^5.72.0", 73 | "webpack-cli": "^4.9.2", 74 | "webpack-merge": "^5.8.0" 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import './styles/style.css'; 2 | import { createTemplate, PersonData, FormLabel } from './template'; 3 | import { createSession } from './xhr'; 4 | 5 | interface Options { 6 | host?: string; 7 | apiKey: string; 8 | parentId: string; 9 | onSession: (err, response) => void; 10 | } 11 | 12 | interface MountOptions { 13 | formLabel?: FormLabel; 14 | submitBtnText?: string; 15 | loadingText?: string; 16 | } 17 | 18 | interface Params { 19 | callback?: string; 20 | person?: PersonData; 21 | vendorData?: string; 22 | } 23 | 24 | const Veriff = (options: Options) => { 25 | const { host = 'https://api.veriff.me', apiKey, parentId, onSession } = options; 26 | const onSessionCallback = onSession; 27 | let mountedOptions: MountOptions = { loadingText: 'Loading...', submitBtnText: 'Start Verification' }; 28 | let params: Params = { 29 | person: {}, 30 | }; 31 | let veriffForm: HTMLFormElement; 32 | 33 | function setParams(newParams: Params): void { 34 | params = { ...params, ...newParams }; 35 | } 36 | 37 | function assignSubmit(form, loadingText = 'Loading...', submitBtnText): HTMLFormElement { 38 | form.onsubmit = (e) => { 39 | e.preventDefault(); 40 | 41 | const callback = params.callback; 42 | const givenName = veriffForm.givenName?.value || params.person.givenName; 43 | const lastName = veriffForm.lastName?.value || params.person.lastName; 44 | const idNumber = params.person?.idNumber; 45 | const vendorData = 46 | typeof veriffForm.vendorData?.value === 'string' ? veriffForm.vendorData?.value : params.vendorData; 47 | 48 | if (!givenName || !lastName) { 49 | throw new Error('Required parameters givenName or lastName is missing'); 50 | } 51 | 52 | setParams({ callback, person: { givenName, lastName, idNumber }, vendorData }); 53 | form.submitBtn.value = loadingText; 54 | form.submitBtn.disabled = true; 55 | createSession(host, apiKey, params, (err, response) => { 56 | if (onSessionCallback) { 57 | onSessionCallback(err, response); 58 | } 59 | form.submitBtn.value = submitBtnText; 60 | form.submitBtn.disabled = false; 61 | }); 62 | }; 63 | 64 | return form; 65 | } 66 | 67 | function mount(mountOptions: MountOptions = {}): void { 68 | mountedOptions = { ...mountedOptions, ...mountOptions }; 69 | const { formLabel, loadingText, submitBtnText } = mountedOptions; 70 | const { person, vendorData } = params; 71 | const form = createTemplate(parentId, { 72 | person, 73 | vendorData, 74 | formLabel, 75 | submitBtnText, 76 | }); 77 | 78 | veriffForm = assignSubmit(form, loadingText, submitBtnText); 79 | } 80 | 81 | return { 82 | params, 83 | setParams, 84 | mount, 85 | }; 86 | }; 87 | 88 | export = Veriff; 89 | -------------------------------------------------------------------------------- /src/styles/style.css: -------------------------------------------------------------------------------- 1 | #veriff-root { 2 | max-width: 400px; 3 | min-width: 208px; 4 | font-family: 'Inter' !important; 5 | } 6 | 7 | .veriff-label { 8 | display: none; 9 | box-sizing: border-box; 10 | margin-bottom: 8px; 11 | color: #505366; 12 | font-size: 14px; 13 | font-weight: 400; 14 | overflow: hidden; 15 | text-overflow: ellipsis; 16 | } 17 | 18 | .veriff-text { 19 | width: 100%; 20 | height: 40px; 21 | padding: 8px 16px; 22 | margin: 0 0 16px; 23 | box-sizing: border-box; 24 | border: 0px; 25 | border-radius: 4px; 26 | appearance: none; 27 | outline: 0px; 28 | font-size: 14px; 29 | font-weight: 400; 30 | background-color: #ffffff; 31 | color: #212121; 32 | transition-duration: 0.24s; 33 | transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); 34 | transition-property: background-color, color, border-color, box-shadow; 35 | box-shadow: 0px 2px 5px rgba(60, 66, 87, 0.08), 0px 0px 0px 1px rgba(60, 66, 87, 0.1), 0px 1px 1px rgba(0, 0, 0, 0.1); 36 | } 37 | 38 | .veriff-text::placeholder { 39 | color: #757575; 40 | } 41 | 42 | .veriff-text:hover { 43 | border-color: #bdc0cf; 44 | box-shadow: 0px 4px 5px rgba(60, 66, 87, 0.12), 0px 0px 0px 1px rgba(60, 66, 87, 0.1), 0px 1px 1px rgba(0, 0, 0, 0.1); 45 | } 46 | 47 | .veriff-text:focus { 48 | box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.1), 0px 0px 0px 1px rgba(0, 78, 95, 0.46), 49 | 0px 0px 0px 4px rgba(212, 250, 237, 1); 50 | } 51 | 52 | .veriff-submit { 53 | width: 100%; 54 | background-color: #11615c; 55 | color: white; 56 | box-sizing: border-box; 57 | text-transform: capitalize; 58 | font-weight: 500; 59 | font-size: 14px; 60 | line-height: 20px; 61 | letter-spacing: -0.005em; 62 | 63 | display: inline-block; 64 | text-align: center; 65 | user-select: none; 66 | border: 1px solid transparent; 67 | 68 | position: relative; 69 | height: 40px; 70 | padding: 0 16px; 71 | border-radius: 4px; 72 | transition-property: color, background-color, box-shadow; 73 | transition-duration: 0.15s; 74 | transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); 75 | text-decoration: none; 76 | user-select: none; 77 | box-shadow: inset 0px 0px 0px 1px rgba(255, 255, 255, 0); 78 | } 79 | 80 | .veriff-submit:hover, 81 | .veriff-submit:focus { 82 | background-color: #29716c; 83 | } 84 | 85 | .veriff-description { 86 | color: #212121; 87 | font-size: 12px; 88 | line-height: 16px; 89 | margin: 16px 0; 90 | text-align: center; 91 | } 92 | 93 | .veriff-description a { 94 | font-weight: 400; 95 | font-size: 12px; 96 | color: #11615c; 97 | } 98 | -------------------------------------------------------------------------------- /src/template.ts: -------------------------------------------------------------------------------- 1 | import { camelCaseToSlug } from './util'; 2 | 3 | export interface FormLabel { 4 | [P: string]: string; 5 | } 6 | 7 | export interface PersonData { 8 | givenName?: string; 9 | lastName?: string; 10 | idNumber?: string; 11 | } 12 | 13 | const defaultFormLabel: FormLabel = { 14 | givenName: 'Given name', 15 | lastName: 'Last name', 16 | idNumber: 'Id number', 17 | vendorData: 'Data', 18 | }; 19 | 20 | const defaultPerson: PersonData = { 21 | givenName: '', 22 | lastName: '', 23 | idNumber: '', 24 | }; 25 | 26 | export interface InputCreationOptions { 27 | type: string; 28 | value?: string; 29 | name: string; 30 | label?: string; 31 | required: boolean; 32 | } 33 | 34 | export function createInput(opts: InputCreationOptions) { 35 | const { type, value, name, label, required } = opts; 36 | const input = document.createElement('input'); 37 | input.setAttribute('type', type); 38 | input.setAttribute('class', `veriff-${type}`); 39 | input.setAttribute('id', `veriff-${camelCaseToSlug(name)}`); 40 | input.setAttribute('name', name); 41 | input.required = required; 42 | 43 | if (type === 'submit' && value) { 44 | input.value = value; 45 | } else { 46 | input.setAttribute('placeholder', label || defaultFormLabel[name]); 47 | } 48 | 49 | return input; 50 | } 51 | 52 | export function createLabel(value = '', labelFor) { 53 | const label = document.createElement('label'); 54 | label.setAttribute('class', `veriff-label`); 55 | label.setAttribute('id', `veriff-label-${camelCaseToSlug(labelFor)}`); 56 | label.setAttribute('htmlFor', labelFor); 57 | label.innerText = value; 58 | return label; 59 | } 60 | 61 | export interface CreationOptions { 62 | container: HTMLFormElement; 63 | name: string; 64 | label: string; 65 | shouldRender: boolean; 66 | required: boolean; 67 | } 68 | 69 | export function createInputIfNeeded(opts: CreationOptions) { 70 | const { container, name, label, shouldRender, required } = opts; 71 | if (shouldRender) { 72 | const inputLabel = createLabel(label, name); 73 | const input = createInput({ type: 'text', name, label, required }); 74 | if (name === 'vendorData') { 75 | input.setAttribute('maxlength', '1000'); 76 | } 77 | 78 | container.appendChild(inputLabel); 79 | container.appendChild(input); 80 | } 81 | } 82 | 83 | export function createDescription() { 84 | const companyLink = document.createElement('a'); 85 | const linkText = document.createTextNode('Veriff'); 86 | companyLink.appendChild(linkText); 87 | companyLink.title = 'Veriff'; 88 | companyLink.href = 'https://www.veriff.com/'; 89 | companyLink.target = '_blank'; 90 | 91 | const description = document.createElement('p'); 92 | const descriptionText = document.createTextNode( 93 | ' is an identity verification provider that helps companies connect with customers.' 94 | ); 95 | description.appendChild(companyLink); 96 | description.appendChild(descriptionText); 97 | description.setAttribute('class', 'veriff-description'); 98 | 99 | return description; 100 | } 101 | 102 | export interface Options { 103 | formLabel?: FormLabel; 104 | person?: PersonData; 105 | vendorData?: string; 106 | submitBtnText?: string; 107 | } 108 | 109 | export function createTemplate(parentId: string, options: Options) { 110 | const { formLabel = defaultFormLabel, person = defaultPerson, vendorData, submitBtnText } = options; 111 | const parent = document.getElementById(parentId); 112 | if (!parent) { 113 | throw new Error(`Element ${parentId} does not exists`); 114 | } 115 | 116 | const fontLink = document.createElement('link'); 117 | fontLink.setAttribute('rel', 'stylesheet'); 118 | fontLink.setAttribute('href', 'https://fonts.googleapis.com/css2?family=Inter:wght@400;500&display=swap'); 119 | document.head.appendChild(fontLink); 120 | 121 | parent.innerHTML = ''; 122 | const fragment = document.createDocumentFragment(); 123 | const container = document.createElement('form'); 124 | 125 | container.setAttribute('class', 'veriff-container'); 126 | container.setAttribute('name', 'veriff-form'); 127 | 128 | createInputIfNeeded({ 129 | container, 130 | name: 'givenName', 131 | label: formLabel.givenName, 132 | shouldRender: !person.givenName, 133 | required: true, 134 | }); 135 | 136 | createInputIfNeeded({ 137 | container, 138 | name: 'lastName', 139 | label: formLabel.lastName, 140 | shouldRender: !person.lastName, 141 | required: true, 142 | }); 143 | 144 | createInputIfNeeded({ 145 | container, 146 | name: 'vendorData', 147 | label: formLabel.vendorData, 148 | shouldRender: !vendorData, 149 | required: true, 150 | }); 151 | 152 | const submit = createInput({ type: 'submit', name: 'submitBtn', value: submitBtnText, required: true }); 153 | container.appendChild(submit); 154 | 155 | const description = createDescription(); 156 | container.appendChild(description); 157 | 158 | fragment.appendChild(container); 159 | parent.appendChild(fragment); 160 | return container; 161 | } 162 | -------------------------------------------------------------------------------- /src/util.ts: -------------------------------------------------------------------------------- 1 | export function capitalize(str: string): string { 2 | return str.charAt(0).toUpperCase() + str.slice(1); 3 | } 4 | 5 | export function camelCaseToSlug(str: string): string { 6 | return str.replace(/([a-zA-Z])(?=[A-Z])/g, '$1-').toLowerCase(); 7 | } 8 | -------------------------------------------------------------------------------- /src/xhr.ts: -------------------------------------------------------------------------------- 1 | import { PersonData } from './template'; 2 | 3 | const CREATED_RESPONSE_STATUS = 201; 4 | 5 | export function createSession( 6 | host: string, 7 | apiKey: string, 8 | data: { callback?: string; person?: PersonData; vendorData?: string }, 9 | cb: (statusObject, resp) => void 10 | ): void { 11 | const url = `${host}/v1/sessions`; 12 | const xhr = new XMLHttpRequest(); 13 | xhr.open('POST', url, true); 14 | xhr.setRequestHeader('Content-type', 'application/json'); 15 | xhr.setRequestHeader('x-auth-client', apiKey); 16 | xhr.setRequestHeader('x-origin', 'js-sdk'); 17 | xhr.onreadystatechange = (): void => { 18 | if (xhr.readyState !== XMLHttpRequest.DONE) { 19 | return; 20 | } 21 | if (xhr.status === CREATED_RESPONSE_STATUS) { 22 | const resp = JSON.parse(xhr.responseText); 23 | return cb(null, resp); 24 | } 25 | return cb( 26 | { 27 | status: xhr.status, 28 | statusText: xhr.statusText, 29 | }, 30 | null 31 | ); 32 | }; 33 | 34 | const body = { 35 | verification: { 36 | callback: data.callback, 37 | person: { 38 | firstName: data.person.givenName, 39 | lastName: data.person.lastName, 40 | idNumber: data.person.idNumber, 41 | }, 42 | vendorData: data.vendorData, 43 | timestamp: new Date().toISOString(), 44 | }, 45 | }; 46 | 47 | const json = JSON.stringify(body); 48 | xhr.send(json); 49 | } 50 | -------------------------------------------------------------------------------- /test/template.test.ts: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | import { createTemplate } from '../src/template'; 3 | 4 | beforeEach(() => { 5 | const veriffRoot = '
'; 6 | document.body.insertAdjacentHTML('afterbegin', veriffRoot); 7 | }); 8 | 9 | afterEach(() => { 10 | document.body.removeChild(document.getElementById('veriff-root')); 11 | }); 12 | 13 | describe('Veriff create template', () => { 14 | it('should create a full template and mount it into root', () => { 15 | createTemplate('veriff-root', {}); 16 | expect(document.querySelector('.veriff-container')).to.exist; 17 | expect(document.getElementById('veriff-label-given-name')).to.exist; 18 | expect(document.getElementById('veriff-given-name')).to.exist; 19 | expect(document.getElementById('veriff-label-last-name')).to.exist; 20 | expect(document.getElementById('veriff-last-name')).to.exist; 21 | expect(document.getElementById('veriff-submit-btn')).to.exist; 22 | }); 23 | 24 | it('should create partial template', () => { 25 | createTemplate('veriff-root', { person: { lastName: '', idNumber: '', givenName: 'foo' }, vendorData: '' }); 26 | expect(document.querySelector('.veriff-container')).to.exist; 27 | expect(document.getElementById('veriff-label-given-name')).not.to.not.exist; 28 | expect(document.getElementById('veriff-given-name')).not.to.exist; 29 | expect(document.getElementById('veriff-label-last-name')).to.exist; 30 | expect(document.getElementById('veriff-last-name')).to.exist; 31 | expect(document.getElementById('veriff-submit-btn')).to.exist; 32 | }); 33 | }); 34 | -------------------------------------------------------------------------------- /test/util.test.ts: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | import * as util from '../src/util'; 3 | 4 | describe('Util', () => { 5 | describe('#capitalize', () => { 6 | it('should capitalize given string', () => { 7 | expect(util.capitalize('foo bar')).to.eql('Foo bar'); 8 | expect(util.capitalize('foo-bar')).to.eql('Foo-bar'); 9 | expect(util.capitalize('Foo bar')).to.eql('Foo bar'); 10 | }); 11 | }); 12 | 13 | describe('#camelCaseToSlug', () => { 14 | it('should slugify the camelCase', () => { 15 | expect(util.camelCaseToSlug('f')).to.eql('f'); 16 | expect(util.camelCaseToSlug('fooBar')).to.eql('foo-bar'); 17 | expect(util.camelCaseToSlug('FooBar')).to.eql('foo-bar'); 18 | }); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /test/xhr.test.ts: -------------------------------------------------------------------------------- 1 | // @ts-ignore 2 | import { IPersonData } from '../src/template'; 3 | 4 | // @ts-ignore 5 | const sinon = require('sinon'); 6 | import { should } from 'chai'; 7 | import { createSession } from '../src/xhr'; 8 | 9 | should(); 10 | 11 | let xhr; 12 | let requests; 13 | 14 | beforeEach(() => { 15 | xhr = sinon.useFakeXMLHttpRequest(); 16 | 17 | requests = []; 18 | xhr.onCreate = function(xhrCopy) { 19 | requests.push(xhrCopy); 20 | }.bind(this); 21 | }); 22 | 23 | afterEach(() => { 24 | xhr.restore(); 25 | }); 26 | 27 | describe('Veriff create session', () => { 28 | it('should submit the verification data', (done) => { 29 | const responseData = JSON.stringify({ url: 'test' }); 30 | const requestData: { callback?: string, person?: IPersonData; vendorData?: string; env: string } = { 31 | callback: 'https://veriff.com', 32 | person: { 33 | givenName: 'test', 34 | lastName: 'test', 35 | }, 36 | env: 'test', 37 | }; 38 | 39 | createSession('test', 'key', requestData, (err, resp) => { 40 | const expectedData = JSON.parse(responseData); 41 | resp.should.deep.equal(expectedData); 42 | done(); 43 | }); 44 | 45 | requests[0].respond( 46 | 201, 47 | { 48 | 'Content-Type': 'text/json', 49 | }, 50 | responseData 51 | ); 52 | }); 53 | 54 | it('should return error status call into callback', (done) => { 55 | const requestData = { 56 | features: [], 57 | person: { 58 | givenName: 'test', 59 | lastName: 'test', 60 | }, 61 | env: 'test', 62 | }; 63 | 64 | createSession('test', '123', requestData, (err) => { 65 | err.should.exist; 66 | err.status.should.eql(500); 67 | err.statusText.should.eql('Internal Server Error'); 68 | done(); 69 | }); 70 | 71 | requests[0].respond(500); 72 | }); 73 | }); 74 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./lib", 4 | "allowJs": true, 5 | "module": "commonjs", 6 | "target": "es5", 7 | "lib": ["es2015", "es2017", "dom"], 8 | "declaration": true 9 | }, 10 | "include": [ 11 | "./src/**/*" 12 | ], 13 | "exclude": [ 14 | "node_modules" 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /webpack/webpack.config.js: -------------------------------------------------------------------------------- 1 | const libraryName = 'Veriff'; 2 | const { merge } = require('webpack-merge'); 3 | 4 | const baseConfig = { 5 | entry: './src/index.ts', 6 | resolve: { 7 | extensions: ['.ts', '.js', '.css'] 8 | }, 9 | }; 10 | 11 | const umdConfig = merge(baseConfig, { 12 | output: { 13 | path: `${__dirname}/../dist`, 14 | filename: 'veriff.min.js', 15 | library: libraryName, 16 | libraryTarget: 'umd', 17 | umdNamedDefine: true 18 | }, 19 | 20 | module: { 21 | rules: [ 22 | { 23 | test: /\.tsx?$/, 24 | use: 'ts-loader', 25 | exclude: /node_modules/, 26 | }, 27 | { 28 | test: /\.css$/, 29 | use: ['style-loader', 'css-loader'], 30 | }, 31 | ], 32 | } 33 | }); 34 | 35 | const npmConfig = merge(baseConfig, { 36 | output: { 37 | path: `${__dirname}/../lib`, 38 | filename: 'veriff.js', 39 | library: libraryName, 40 | libraryTarget: 'commonjs2' 41 | }, 42 | 43 | module: { 44 | rules: [ 45 | { 46 | test: /\.tsx?$/, 47 | use: 'ts-loader', 48 | exclude: /node_modules/, 49 | }, 50 | { 51 | test: /\.css$/, 52 | use: ['style-loader', 'css-loader'], 53 | }, 54 | ], 55 | } 56 | }); 57 | 58 | module.exports = [umdConfig, npmConfig]; 59 | --------------------------------------------------------------------------------