├── .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 | 
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 | 
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 | 
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 |
--------------------------------------------------------------------------------