Skip to content
Merged
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
1 change: 0 additions & 1 deletion app/controllers/verify_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ def app_data

{
base_path: idv_app_path,
app_name: APP_NAME,
completion_url: completion_url,
initial_values: initial_values,
enabled_step_names: IdentityConfig.store.idv_api_enabled_steps,
Expand Down
20 changes: 0 additions & 20 deletions app/javascript/packages/analytics/index.js

This file was deleted.

20 changes: 20 additions & 0 deletions app/javascript/packages/analytics/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { getConfigValue } from '@18f/identity-config';

/**
* Logs an event.
*
* @param event Event name.
* @param payload Payload object.
*
* @return Promise resolving once event has been logged.
*/
export async function trackEvent(event: string, payload: object = {}): Promise<void> {
const endpoint = getConfigValue('analyticsEndpoint');
if (endpoint) {
await window.fetch(endpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ event, payload }),
});
}
}
32 changes: 32 additions & 0 deletions app/javascript/packages/config/get-config-value.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import getConfigValue from './get-config-value';
import type { Config } from './get-config-value';

describe('getConfigValue', () => {
context('with page config element absent', () => {
it('returns undefined', () => {
expect(getConfigValue('appName')).to.be.undefined();
expect(getConfigValue('analyticsEndpoint')).to.be.undefined();
});
});

context('with page config element present', () => {
const APP_NAME = 'app';
const ANALYTICS_ENDPOINT = 'url';

beforeEach(() => {
const config = document.createElement('script');
config.type = 'application/json';
config.setAttribute('data-config', '');
config.textContent = JSON.stringify({
appName: APP_NAME,
analyticsEndpoint: ANALYTICS_ENDPOINT,
} as Config);
document.body.appendChild(config);
});

it('returns the config value corresponding to the given key', () => {
expect(getConfigValue('appName')).to.equal(APP_NAME);
expect(getConfigValue('analyticsEndpoint')).to.equal(ANALYTICS_ENDPOINT);
});
});
});
45 changes: 45 additions & 0 deletions app/javascript/packages/config/get-config-value.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/**
* Supported page configuration values.
*/
export interface Config {
/**
* Application name.
*/
appName: string;

/**
* URL for analytics logging endpoint.
*/
analyticsEndpoint: string;
}

/**
* Cached configuration.
*/
let cache: Partial<Config>;

/**
* Whether configuration should be cached in this environment.
*/
const isCacheEnvironment = process.env.NODE_ENV !== 'test';

/**
* Returns the value associated as initialized through page configuration, if available.
*
* @param key Key for which to return value.
*
* @return Value, if exists.
*/
function getConfigValue<K extends keyof Config>(key: K): Config[K] | undefined {
if (cache === undefined || !isCacheEnvironment) {
try {
cache = JSON.parse(document.querySelector('[data-config]')?.textContent || '');
} catch {
cache = {};
}
}

return cache[key];
}

export default getConfigValue;
1 change: 1 addition & 0 deletions app/javascript/packages/config/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as getConfigValue } from './get-config-value';
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "@18f/identity-page-data",
"name": "@18f/identity-config",
"private": true,
"version": "1.0.0"
}
37 changes: 0 additions & 37 deletions app/javascript/packages/page-data/index.js

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { t } from '@18f/identity-i18n';
import { getConfigValue } from '@18f/identity-config';
import type { FormStep } from '@18f/identity-form-steps';
import type { VerifyFlowValues } from '../../verify-flow';
import form from './password-confirm-step';
import submit from './submit';

export default {
name: 'password_confirm',
title: t('idv.titles.session.review'),
title: t('idv.titles.session.review', { app_name: getConfigValue('appName') }),
form,
submit,
} as FormStep<VerifyFlowValues>;
9 changes: 2 additions & 7 deletions app/javascript/packages/verify-flow/verify-flow.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,14 @@ describe('VerifyFlow', () => {
sandbox.stub(window, 'fetch').resolves({
json: () => Promise.resolve({ personal_key: personalKey }),
} as Response);
document.body.innerHTML = `<script type="application/json" data-config>{"appName":"Example App"}</script>`;
});

it('advances through flow to completion', async () => {
const onComplete = sandbox.spy();

const { getByText, findByText, getByLabelText } = render(
<VerifyFlow
appName="Example App"
initialValues={{ personalKey }}
onComplete={onComplete}
basePath="/"
/>,
<VerifyFlow initialValues={{ personalKey }} onComplete={onComplete} basePath="/" />,
);

// Password confirm
Expand Down Expand Up @@ -59,7 +55,6 @@ describe('VerifyFlow', () => {
it('sets details according to the first enabled steps', () => {
render(
<VerifyFlow
appName="Example App"
initialValues={{ personalKey }}
onComplete={() => {}}
enabledStepNames={[STEPS[1].name]}
Expand Down
9 changes: 2 additions & 7 deletions app/javascript/packages/verify-flow/verify-flow.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useEffect, useState } from 'react';
import { FormSteps } from '@18f/identity-form-steps';
import { trackEvent } from '@18f/identity-analytics';
import { getConfigValue } from '@18f/identity-config';
import { STEPS } from './steps';
import VerifyFlowStepIndicator from './verify-flow-step-indicator';
import VerifyFlowAlert from './verify-flow-alert';
Expand Down Expand Up @@ -51,11 +52,6 @@ interface VerifyFlowProps {
*/
basePath: string;

/**
* Application name, used in generating page titles for current step.
*/
appName: string;

/**
* Callback invoked after completing the form.
*/
Expand Down Expand Up @@ -87,7 +83,6 @@ function VerifyFlow({
initialValues = {},
enabledStepNames,
basePath,
appName,
onComplete,
}: VerifyFlowProps) {
let steps = STEPS;
Expand Down Expand Up @@ -117,7 +112,7 @@ function VerifyFlow({
initialStep={initialStep}
promptOnNavigate={false}
basePath={basePath}
titleFormat={`%{step} - ${appName}`}
titleFormat={`%{step} - ${getConfigValue('appName')}`}
onChange={setSyncedValues}
onStepSubmit={onStepSubmit}
onStepChange={setCurrentStep}
Expand Down
12 changes: 0 additions & 12 deletions app/javascript/packs/doc-capture-polling.js

This file was deleted.

11 changes: 11 additions & 0 deletions app/javascript/packs/doc-capture-polling.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { DocumentCapturePolling } from '@18f/identity-document-capture-polling';

new DocumentCapturePolling({
statusEndpoint: document
.querySelector('[data-status-endpoint]')
?.getAttribute('data-status-endpoint') as string,
elements: {
backLink: document.querySelector('.link-sent-back-link') as HTMLAnchorElement,
form: document.querySelector('.link-sent-continue-button-form') as HTMLFormElement,
},
}).bind();
7 changes: 0 additions & 7 deletions app/javascript/packs/verify-flow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,6 @@ interface AppRootValues {
*/
basePath: string;

/**
* Application name.
*/
appName: string;

/**
* URL to which user should be redirected after completing the form.
*/
Expand All @@ -49,7 +44,6 @@ const {
initialValues: initialValuesJSON,
enabledStepNames: enabledStepNamesJSON,
basePath,
appName,
completionUrl: completionURL,
storeKey: storeKeyBase64,
} = appRoot.dataset;
Expand Down Expand Up @@ -93,7 +87,6 @@ const storage = new SecretSessionStorage<SecretValues>('verify');
initialValues={initialValues}
enabledStepNames={enabledStepNames}
basePath={basePath}
appName={appName}
onComplete={onComplete}
/>
</SecretsContextProvider>,
Expand Down
2 changes: 1 addition & 1 deletion app/views/idv/doc_auth/link_sent.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
</div>

<% if FeatureManagement.doc_capture_polling_enabled? %>
<%= content_tag 'script', '', data: { doc_capture_status_endpoint: idv_capture_doc_status_url } %>
<%= content_tag 'script', '', data: { status_endpoint: idv_capture_doc_status_url } %>
<%= javascript_packs_tag_once 'doc-capture-polling' %>
<% end %>

Expand Down
10 changes: 9 additions & 1 deletion app/views/layouts/base.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,15 @@
} %>
<% end %>

<%= content_tag 'script', '', data: { analytics_endpoint: api_logger_path } %>
<%= content_tag(
:script,
{
'appName' => APP_NAME,
'analyticsEndpoint' => api_logger_path,
}.to_json,
{ type: 'application/json', data: { config: '' } },
false,
) %>
<%= javascript_packs_tag_once('application', prepend: true) %>
<%= render_javascript_pack_once_tags %>

Expand Down
2 changes: 0 additions & 2 deletions spec/controllers/verify_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@
response

expect(assigns[:app_data]).to include(
app_name: APP_NAME,
base_path: idv_app_path,
completion_url: idv_gpo_verify_url,
enabled_step_names: idv_api_enabled_steps,
Expand Down Expand Up @@ -97,7 +96,6 @@
response

expect(assigns[:app_data]).to include(
app_name: APP_NAME,
base_path: idv_app_path,
completion_url: account_url,
enabled_step_names: idv_api_enabled_steps,
Expand Down
14 changes: 6 additions & 8 deletions spec/features/visitors/i18n_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,9 @@
end

it 'initializes front-end logger with default locale' do
expect(page).to have_selector(
"[data-analytics-endpoint='#{api_logger_path(locale: nil)}']",
visible: :all,
)
config = JSON.parse(page.find('[data-config]', visible: :all).text(:all))

expect(config['analyticsEndpoint']).to eq api_logger_path(locale: nil)
end
end

Expand All @@ -37,10 +36,9 @@
end

it 'initializes front-end logger with locale parameter' do
expect(page).to have_selector(
"[data-analytics-endpoint='#{api_logger_path(locale: 'es')}']",
visible: :all,
)
config = JSON.parse(page.find('[data-config]', visible: :all).text(:all))

expect(config['analyticsEndpoint']).to eq api_logger_path(locale: 'es')
end
end

Expand Down
2 changes: 1 addition & 1 deletion spec/javascripts/packages/analytics/index-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ describe('trackEvent', () => {
const endpoint = '/log';

beforeEach(() => {
document.body.innerHTML = `<script data-analytics-endpoint="${endpoint}"></script>`;
document.body.innerHTML = `<script type="application/json" data-config>{"analyticsEndpoint":"${endpoint}"}</script>`;
});

context('no payload', () => {
Expand Down
Loading