зеркало из https://github.com/mozilla/fxa.git
respect metrics opt-out flag
This commit is contained in:
Родитель
3da291f829
Коммит
d0f7bcd26c
|
@ -23,11 +23,18 @@ import { MockStatsDProvider } from '@fxa/shared/metrics/statsd';
|
||||||
import { PriceManager } from '@fxa/payments/customer';
|
import { PriceManager } from '@fxa/payments/customer';
|
||||||
import { MockFirestoreProvider } from '@fxa/shared/db/firestore';
|
import { MockFirestoreProvider } from '@fxa/shared/db/firestore';
|
||||||
import { MockPaymentsGleanFactory } from './glean.provider';
|
import { MockPaymentsGleanFactory } from './glean.provider';
|
||||||
|
import {
|
||||||
|
AccountFactory,
|
||||||
|
MockAccountDatabaseNestFactory,
|
||||||
|
} from '@fxa/shared/db/mysql/account';
|
||||||
|
import { AccountManager } from '@fxa/shared/account/account';
|
||||||
|
import { faker } from '@faker-js/faker';
|
||||||
|
|
||||||
describe('PaymentsGleanService', () => {
|
describe('PaymentsGleanService', () => {
|
||||||
let paymentsGleanService: PaymentsGleanService;
|
let paymentsGleanService: PaymentsGleanService;
|
||||||
let paymentsGleanManager: PaymentsGleanManager;
|
let paymentsGleanManager: PaymentsGleanManager;
|
||||||
let productConfigurationManager: ProductConfigurationManager;
|
let productConfigurationManager: ProductConfigurationManager;
|
||||||
|
let accountsManager: AccountManager;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
const moduleRef = await Test.createTestingModule({
|
const moduleRef = await Test.createTestingModule({
|
||||||
|
@ -35,6 +42,7 @@ describe('PaymentsGleanService', () => {
|
||||||
MockPaymentsGleanFactory,
|
MockPaymentsGleanFactory,
|
||||||
MockStrapiClientConfigProvider,
|
MockStrapiClientConfigProvider,
|
||||||
MockStripeConfigProvider,
|
MockStripeConfigProvider,
|
||||||
|
MockAccountDatabaseNestFactory,
|
||||||
MockFirestoreProvider,
|
MockFirestoreProvider,
|
||||||
MockStatsDProvider,
|
MockStatsDProvider,
|
||||||
StrapiClient,
|
StrapiClient,
|
||||||
|
@ -43,18 +51,21 @@ describe('PaymentsGleanService', () => {
|
||||||
PaymentsGleanManager,
|
PaymentsGleanManager,
|
||||||
ProductConfigurationManager,
|
ProductConfigurationManager,
|
||||||
PaymentsGleanService,
|
PaymentsGleanService,
|
||||||
|
AccountManager,
|
||||||
],
|
],
|
||||||
}).compile();
|
}).compile();
|
||||||
|
|
||||||
paymentsGleanService = moduleRef.get(PaymentsGleanService);
|
paymentsGleanService = moduleRef.get(PaymentsGleanService);
|
||||||
paymentsGleanManager = moduleRef.get(PaymentsGleanManager);
|
paymentsGleanManager = moduleRef.get(PaymentsGleanManager);
|
||||||
productConfigurationManager = moduleRef.get(ProductConfigurationManager);
|
productConfigurationManager = moduleRef.get(ProductConfigurationManager);
|
||||||
|
accountsManager = moduleRef.get(AccountManager);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be defined', () => {
|
it('should be defined', () => {
|
||||||
expect(paymentsGleanService).toBeDefined();
|
expect(paymentsGleanService).toBeDefined();
|
||||||
expect(paymentsGleanManager).toBeDefined();
|
expect(paymentsGleanManager).toBeDefined();
|
||||||
expect(productConfigurationManager).toBeDefined();
|
expect(productConfigurationManager).toBeDefined();
|
||||||
|
expect(accountsManager).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('handleEventFxaPaySetupView', () => {
|
describe('handleEventFxaPaySetupView', () => {
|
||||||
|
@ -106,5 +117,27 @@ describe('PaymentsGleanService', () => {
|
||||||
{ priceId: '', productId: '' }
|
{ priceId: '', productId: '' }
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should not call recordFxaPaySetupView if opted out', async () => {
|
||||||
|
const uid = Buffer.from(
|
||||||
|
faker.string.hexadecimal({
|
||||||
|
length: 32,
|
||||||
|
prefix: '',
|
||||||
|
casing: 'lower',
|
||||||
|
}),
|
||||||
|
'hex'
|
||||||
|
);
|
||||||
|
const mockUser = AccountFactory({
|
||||||
|
uid,
|
||||||
|
metricsOptOutAt: new Date().valueOf(),
|
||||||
|
});
|
||||||
|
jest.spyOn(accountsManager, 'getAccounts').mockResolvedValue([mockUser]);
|
||||||
|
|
||||||
|
await paymentsGleanService.handleEventFxaPaySetupView({
|
||||||
|
...mockMetricsData,
|
||||||
|
uid: uid.toString('hex'),
|
||||||
|
});
|
||||||
|
expect(paymentsGleanManager.recordFxaPaySetupView).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -7,6 +7,7 @@ import { ProductConfigurationManager } from '@fxa/shared/cms';
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { mapParams } from './utils/mapParams';
|
import { mapParams } from './utils/mapParams';
|
||||||
import { PaymentsGleanManager } from './glean.manager';
|
import { PaymentsGleanManager } from './glean.manager';
|
||||||
|
import { AccountManager } from '@fxa/shared/account/account';
|
||||||
import { SubplatInterval } from '@fxa/payments/customer';
|
import { SubplatInterval } from '@fxa/payments/customer';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
|
@ -15,7 +16,8 @@ export class PaymentsGleanService {
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private productConfigurationManager: ProductConfigurationManager,
|
private productConfigurationManager: ProductConfigurationManager,
|
||||||
private paymentsGleanManager: PaymentsGleanManager
|
private paymentsGleanManager: PaymentsGleanManager,
|
||||||
|
private accountManager: AccountManager
|
||||||
) {
|
) {
|
||||||
this.emitter = new Emittery<GleanEvents>();
|
this.emitter = new Emittery<GleanEvents>();
|
||||||
this.emitter.on(
|
this.emitter.on(
|
||||||
|
@ -30,9 +32,17 @@ export class PaymentsGleanService {
|
||||||
|
|
||||||
async handleEventFxaPaySetupView(metricsData: FxaPaySetupViewMetrics) {
|
async handleEventFxaPaySetupView(metricsData: FxaPaySetupViewMetrics) {
|
||||||
const { offeringId, interval } = mapParams(metricsData.params);
|
const { offeringId, interval } = mapParams(metricsData.params);
|
||||||
const cmsData = await this.retrieveCMSData(offeringId, interval);
|
const [cmsData, optedOut] = await Promise.all([
|
||||||
|
this.retrieveCMSData(offeringId, interval),
|
||||||
|
this.retrieveOptOut(metricsData.uid),
|
||||||
|
]);
|
||||||
|
|
||||||
await this.paymentsGleanManager.recordFxaPaySetupView(metricsData, cmsData);
|
if (!optedOut) {
|
||||||
|
await this.paymentsGleanManager.recordFxaPaySetupView(
|
||||||
|
metricsData,
|
||||||
|
cmsData
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async retrieveCMSData(offeringId: string, interval: SubplatInterval) {
|
private async retrieveCMSData(offeringId: string, interval: SubplatInterval) {
|
||||||
|
@ -53,4 +63,10 @@ export class PaymentsGleanService {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async retrieveOptOut(uid?: string): Promise<boolean> {
|
||||||
|
if (!uid) return false;
|
||||||
|
const accounts = await this.accountManager.getAccounts([uid]);
|
||||||
|
return accounts[0].metricsOptOutAt !== null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ export * from './lib/associated-types';
|
||||||
export * from './lib/kysely-types';
|
export * from './lib/kysely-types';
|
||||||
export {
|
export {
|
||||||
CartFactory,
|
CartFactory,
|
||||||
|
AccountFactory,
|
||||||
AccountCustomerFactory,
|
AccountCustomerFactory,
|
||||||
PaypalCustomerFactory,
|
PaypalCustomerFactory,
|
||||||
} from './lib/factories';
|
} from './lib/factories';
|
||||||
|
|
|
@ -4,7 +4,12 @@
|
||||||
|
|
||||||
import { faker } from '@faker-js/faker';
|
import { faker } from '@faker-js/faker';
|
||||||
|
|
||||||
import { AccountCustomer, NewCart, PaypalCustomer } from './associated-types';
|
import {
|
||||||
|
Account,
|
||||||
|
AccountCustomer,
|
||||||
|
NewCart,
|
||||||
|
PaypalCustomer,
|
||||||
|
} from './associated-types';
|
||||||
import { CartEligibilityStatus, CartState } from './kysely-types';
|
import { CartEligibilityStatus, CartState } from './kysely-types';
|
||||||
|
|
||||||
export const CartFactory = (override?: Partial<NewCart>): NewCart => ({
|
export const CartFactory = (override?: Partial<NewCart>): NewCart => ({
|
||||||
|
@ -39,6 +44,51 @@ export const CartFactory = (override?: Partial<NewCart>): NewCart => ({
|
||||||
...override,
|
...override,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const getHexBuffer = (length: number, prefix = ''): Buffer => {
|
||||||
|
return Buffer.from(
|
||||||
|
faker.string.hexadecimal({
|
||||||
|
length,
|
||||||
|
prefix,
|
||||||
|
casing: 'lower',
|
||||||
|
}),
|
||||||
|
'hex'
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const AccountFactory = (override?: Partial<Account>): Account => ({
|
||||||
|
uid: getHexBuffer(32),
|
||||||
|
createdAt: faker.date.recent().getTime(),
|
||||||
|
email: faker.internet.email(),
|
||||||
|
normalizedEmail: faker.internet.email().toLocaleLowerCase(),
|
||||||
|
emailCode: getHexBuffer(16),
|
||||||
|
emailVerified: 1,
|
||||||
|
verifierVersion: 1,
|
||||||
|
kA: getHexBuffer(32),
|
||||||
|
wrapWrapKb: Buffer.from(
|
||||||
|
faker.string.hexadecimal({
|
||||||
|
length: 32,
|
||||||
|
prefix: '',
|
||||||
|
casing: 'lower',
|
||||||
|
}),
|
||||||
|
'hex'
|
||||||
|
),
|
||||||
|
wrapWrapKbVersion2: getHexBuffer(32),
|
||||||
|
authSalt: getHexBuffer(32),
|
||||||
|
verifyHash: getHexBuffer(32),
|
||||||
|
verifierSetAt: faker.date.recent().getTime(),
|
||||||
|
verifyHashVersion2: getHexBuffer(32),
|
||||||
|
locale: 'en-US',
|
||||||
|
lockedAt: null,
|
||||||
|
profileChangedAt: null,
|
||||||
|
keysChangedAt: null,
|
||||||
|
ecosystemAnonId: faker.string.numeric(),
|
||||||
|
disabledAt: null,
|
||||||
|
metricsOptOutAt: null,
|
||||||
|
clientSalt: null,
|
||||||
|
atLeast18AtReg: 1,
|
||||||
|
...override,
|
||||||
|
});
|
||||||
|
|
||||||
export const AccountCustomerFactory = (
|
export const AccountCustomerFactory = (
|
||||||
override?: Partial<AccountCustomer>
|
override?: Partial<AccountCustomer>
|
||||||
): AccountCustomer => ({
|
): AccountCustomer => ({
|
||||||
|
|
Загрузка…
Ссылка в новой задаче