Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion packages/verify/src/embedded.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export default class AuthSession {
this.key = key;
this.listen = {};
this.locale = '';
this.custom = null;
this.endpoint = 'https://app.clicksign.com';
this.origin = `${window.location.protocol}://${window.location.host}`;
}
Expand Down Expand Up @@ -56,8 +57,32 @@ export default class AuthSession {
return `${this.endpoint}${this.path}${this.params}`;
}

// TODO: Definir nome do método combinando com o nome do query param (linha 81)
get data() {
if (!this.custom) return '';

return AuthSession.base64EncodeUrl(JSON.stringify({ custom: this.custom }));
}

static base64EncodeUrl(value) {
let base64;

if (typeof btoa === 'function') base64 = btoa(value);
else if (typeof Buffer !== 'undefined') base64 = Buffer.from(value, 'utf-8').toString('base64');
else throw new Error('No base64 encoder available');

return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/g, '');
}

get params() {
return `?origin=${this.origin}`;
const query = new URLSearchParams({ origin: this.origin });

// TODO: Definir nome do query param. Ex.: settings, payload, data, etc.
if (this.data) query.set('data', this.data);

const queryToString = query.toString();

return queryToString ? `?${queryToString}` : '';
}

get path() {
Expand Down
64 changes: 62 additions & 2 deletions packages/verify/src/embedded.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,21 @@ const sessionKey = 'foobar123';
const endpoint = 'https://example.com';
const originUrl = `${window.location.protocol}://${window.location.host}`;

function getSourceUrl(locale = '') {
function getDataParam(custom = null) {
if (!custom) return '';

return AuthSession.base64EncodeUrl(JSON.stringify({ custom }));
}

function getSourceUrl(locale = '', custom = null) {
const prefix = `${endpoint}/verify`;
const verifyPath = locale ? `${prefix}/${locale}` : prefix;
const query = new URLSearchParams({ origin: originUrl });
const data = getDataParam(custom);

if (data) query.set('data', data);

return `${verifyPath}/sessions/${sessionKey}?origin=${originUrl}`;
return `${verifyPath}/sessions/${sessionKey}?${query.toString()}`;
}

function createContainerElement() {
Expand All @@ -27,6 +37,8 @@ describe('AuthSession', () => {

instance.endpoint = endpoint;
instance.origin = originUrl;
instance.locale = '';
instance.custom = null;
instance.listen = {};
});

Expand All @@ -39,6 +51,7 @@ describe('AuthSession', () => {
expect(instance.origin).toBe(originUrl);
expect(instance.endpoint).toBe(endpoint);
expect(instance.locale).toBe('');
expect(instance.custom).toBeNull();
expect(instance.source).toBe(getSourceUrl());
});

Expand Down Expand Up @@ -102,6 +115,53 @@ describe('AuthSession', () => {
});
});

describe('Customization', () => {
it('should initialize custom as null by default', () => {
expect(instance.custom).toBeNull();
});

it('should include custom colors in data query param in the iframe source URL when custom colors is set', () => {
const custom = {
colors: {
buttonTextColor: '#ffffff',
buttonBackgroundColor: '#000000',
},
};

instance.custom = custom;
instance.start(containerElementId);

const iframeElement = document.getElementById(containerElementId).children[0];
const iframeSrcUrl = new URL(iframeElement.src);

expect(instance.params).toContain('data=');
expect(instance.source).toBe(getSourceUrl('', custom));
expect(iframeSrcUrl.searchParams.get('data')).toBe(getDataParam(custom));
});
});

describe('Query Params', () => {
it('should include origin query param in the iframe source URL', () => {
instance.start(containerElementId);

const iframeElement = document.getElementById(containerElementId).children[0];
const iframeSrcUrl = new URL(iframeElement.src);

expect(instance.params).toBe(`?${new URLSearchParams({ origin: originUrl }).toString()}`);
expect(iframeSrcUrl.searchParams.get('origin')).toBe(originUrl);
});

it('should not include data query param when there is no payload', () => {
instance.start(containerElementId);

const iframeElement = document.getElementById(containerElementId).children[0];
const iframeSrcUrl = new URL(iframeElement.src);

expect(instance.params).not.toContain('data=');
expect(iframeSrcUrl.searchParams.get('data')).toBeNull();
});
});

describe('Events', () => {
const eventMock = vi.fn();
const events = ['loaded', 'completed', 'error'];
Expand Down