refactor: retire legacy tbank-sync status and sync=observe (WealthLedger/backend#196)
This commit is contained in:
@@ -153,19 +153,19 @@ describe('local accounts and portfolio HTTP (SQLite)', () => {
|
||||
encryptedToken: app.get(TbankTokenService).encrypt('synthetic'),
|
||||
},
|
||||
});
|
||||
const cold = await get('brokerage-accounts/unknown/portfolio?sync=observe').expect(200);
|
||||
const cold = await get('brokerage-accounts/unknown/portfolio').expect(200);
|
||||
expect((cold.body as PortfolioResourceDto).data).toBeNull();
|
||||
expect((cold.body as PortfolioResourceDto).meta.availability).toBe(
|
||||
'temporarily-unavailable',
|
||||
);
|
||||
await get('brokerage-accounts?sync=observe').expect(200);
|
||||
await get('brokerage-accounts').expect(200);
|
||||
expect(upstream.getOpenAccounts).not.toHaveBeenCalled();
|
||||
expect(upstream.getPortfolio).not.toHaveBeenCalled();
|
||||
const connection = await prisma.tbankConnection.findUniqueOrThrow({ where: { userId: 'owner' } });
|
||||
await prisma.tbankAccount.create({ data: { userId: 'owner', revision: connection.revision, accountId: 'account', name: 'Synthetic', type: 'ACCOUNT_TYPE_TINKOFF', upstreamOrder: 0 } });
|
||||
await prisma.tbankConnection.update({ where: { userId: 'owner' }, data: { membershipAt: new Date() } });
|
||||
await get('brokerage-accounts/unknown/portfolio?sync=observe').expect(404);
|
||||
await get('brokerage-accounts?sync=observe', 'other').expect(409);
|
||||
await get('brokerage-accounts/unknown/portfolio').expect(404);
|
||||
await get('brokerage-accounts', 'other').expect(409);
|
||||
await get('brokerage-accounts?sync=unexpected').expect(200);
|
||||
});
|
||||
|
||||
@@ -192,7 +192,7 @@ describe('local accounts and portfolio HTTP (SQLite)', () => {
|
||||
await seedMembership();
|
||||
const blocked = deferred<TbankPortfolio>();
|
||||
upstream.getPortfolio.mockReturnValueOnce(blocked.promise);
|
||||
const cold = await get('brokerage-accounts?sync=observe').expect(200);
|
||||
const cold = await get('brokerage-accounts').expect(200);
|
||||
expect(
|
||||
(cold.body as BrokerageAccountsResourceDto).data?.[0].portfolioSummary,
|
||||
).toBeNull();
|
||||
@@ -270,7 +270,7 @@ describe('local accounts and portfolio HTTP (SQLite)', () => {
|
||||
if (work) await work.done;
|
||||
await settled();
|
||||
const before = (
|
||||
await get('brokerage-accounts/account/portfolio?sync=observe').expect(200)
|
||||
await get('brokerage-accounts/account/portfolio').expect(200)
|
||||
).body as PortfolioResourceDto;
|
||||
const fetchedAt = new Date();
|
||||
await prisma.tbankInstrument.create({
|
||||
@@ -307,7 +307,7 @@ describe('local accounts and portfolio HTTP (SQLite)', () => {
|
||||
update: { matchedUids: ['enriched-stock'], fetchedAt },
|
||||
});
|
||||
const after = (
|
||||
await get('brokerage-accounts/account/portfolio?sync=observe').expect(200)
|
||||
await get('brokerage-accounts/account/portfolio').expect(200)
|
||||
).body as PortfolioResourceDto;
|
||||
expect(after.data?.positions[0]).toMatchObject({
|
||||
displayName: 'Enriched name',
|
||||
@@ -333,7 +333,7 @@ describe('local accounts and portfolio HTTP (SQLite)', () => {
|
||||
where: { userId: 'owner', scopeKey: 'portfolio:account' },
|
||||
data: { state: 'complete' },
|
||||
});
|
||||
const stale = await get('brokerage-accounts/account/portfolio?sync=observe').expect(200);
|
||||
const stale = await get('brokerage-accounts/account/portfolio').expect(200);
|
||||
const previous = (stale.body as PortfolioResourceDto).data;
|
||||
expect(previous?.isStale).toBe(true);
|
||||
expect(previous?.lastSuccessfulAt).toBe(new Date(0).toISOString());
|
||||
@@ -343,7 +343,7 @@ describe('local accounts and portfolio HTTP (SQLite)', () => {
|
||||
data: { state: 'failed', errorCode: 'TBANK_UNAVAILABLE' },
|
||||
});
|
||||
const failed = await get(
|
||||
'brokerage-accounts/account/portfolio?sync=observe',
|
||||
'brokerage-accounts/account/portfolio',
|
||||
).expect(200);
|
||||
expect((failed.body as PortfolioResourceDto).data).toEqual(previous);
|
||||
expect((failed.body as PortfolioResourceDto).meta.lastAttempt.state).toBe('none');
|
||||
@@ -403,7 +403,7 @@ describe('local accounts and portfolio HTTP (SQLite)', () => {
|
||||
},
|
||||
]);
|
||||
const income = await get(
|
||||
'brokerage-accounts/account/income-analytics?sync=observe',
|
||||
'brokerage-accounts/account/income-analytics',
|
||||
).expect(200);
|
||||
const incomeMeta = (income.body as IncomeAnalyticsResourceDto).meta;
|
||||
expect(incomeMeta.lastAttempt.state).toBe('partial');
|
||||
@@ -443,7 +443,7 @@ describe('local accounts and portfolio HTTP (SQLite)', () => {
|
||||
});
|
||||
const blocked = deferred<TbankAccount[]>();
|
||||
upstream.getOpenAccounts.mockReturnValueOnce(blocked.promise);
|
||||
await get('brokerage-accounts?sync=observe').expect(200);
|
||||
await get('brokerage-accounts').expect(200);
|
||||
expect(upstream.getOpenAccounts).not.toHaveBeenCalled();
|
||||
expect(
|
||||
(
|
||||
@@ -468,9 +468,9 @@ describe('local accounts and portfolio HTTP (SQLite)', () => {
|
||||
where: { id: 'abandoned-membership' },
|
||||
data: { state: 'complete' },
|
||||
});
|
||||
expect((await get('brokerage-accounts/account/portfolio?sync=observe').expect(200)).body).toMatchObject({ data: null, meta: { availability: 'temporarily-unavailable', completeness: 'incomplete' } });
|
||||
expect((await get('brokerage-accounts/account/portfolio').expect(200)).body).toMatchObject({ data: null, meta: { availability: 'temporarily-unavailable', completeness: 'incomplete' } });
|
||||
expect(await prisma.tbankPortfolio.count()).toBe(0);
|
||||
expect((await get('brokerage-accounts?sync=observe')).body).toMatchObject({
|
||||
expect((await get('brokerage-accounts')).body).toMatchObject({
|
||||
data: [{ id: 'account', portfolioSummary: null }],
|
||||
});
|
||||
});
|
||||
@@ -510,7 +510,7 @@ describe('local accounts and portfolio HTTP (SQLite)', () => {
|
||||
}
|
||||
await delay(5);
|
||||
}
|
||||
const summaries = (await get('brokerage-accounts?sync=observe').expect(200))
|
||||
const summaries = (await get('brokerage-accounts').expect(200))
|
||||
.body as BrokerageAccountsResourceDto;
|
||||
expect(summaries.data?.[0].portfolioSummary).toMatchObject({
|
||||
totalsByCurrency: [{ currency: 'RUB', value: '21.1' }],
|
||||
@@ -528,10 +528,10 @@ describe('local accounts and portfolio HTTP (SQLite)', () => {
|
||||
expect(summaries.meta.availability).toBe('available');
|
||||
expect(summaries.meta.completeness).toBe('complete');
|
||||
expect(
|
||||
(await get('brokerage-accounts/all/portfolio?sync=observe')).body,
|
||||
(await get('brokerage-accounts/all/portfolio')).body,
|
||||
).toMatchObject({ data: null, meta: { availability: 'temporarily-unavailable', completeness: 'incomplete' } });
|
||||
expect(
|
||||
(await get(`stocks/${uid}/position?sync=observe`).expect(200)).body,
|
||||
(await get(`stocks/${uid}/position`).expect(200)).body,
|
||||
).toMatchObject({ data: null, meta: { availability: 'temporarily-unavailable', completeness: 'incomplete' } });
|
||||
expect(upstream.getPortfolio).toHaveBeenCalledTimes(2);
|
||||
await prisma.tbankAccount.deleteMany({ where: { accountId: 'second' } });
|
||||
@@ -542,7 +542,7 @@ describe('local accounts and portfolio HTTP (SQLite)', () => {
|
||||
await prisma.tbankConnection.updateMany({
|
||||
data: { membershipRevision: { increment: 1 } },
|
||||
});
|
||||
const position = await get(`stocks/${uid}/position?sync=observe`).expect(
|
||||
const position = await get(`stocks/${uid}/position`).expect(
|
||||
200,
|
||||
);
|
||||
expect(position.body).toMatchObject({
|
||||
@@ -551,12 +551,12 @@ describe('local accounts and portfolio HTTP (SQLite)', () => {
|
||||
});
|
||||
await prisma.$disconnect();
|
||||
expect(
|
||||
(await get(`stocks/${uid}/position?sync=observe`).expect(200)).body,
|
||||
(await get(`stocks/${uid}/position`).expect(200)).body,
|
||||
).toEqual(position.body);
|
||||
expect(upstream.getOpenAccounts).not.toHaveBeenCalled();
|
||||
expect(upstream.getPortfolio).toHaveBeenCalledTimes(2);
|
||||
await prisma.tbankConnection.updateMany({ data: { invalidToken: true } });
|
||||
await get(`stocks/${uid}/position?sync=observe`).expect(400);
|
||||
await get(`stocks/${uid}/position`).expect(400);
|
||||
});
|
||||
|
||||
it('uses membership TTL for an empty aggregate without starting work through observation', async () => {
|
||||
@@ -570,7 +570,7 @@ describe('local accounts and portfolio HTTP (SQLite)', () => {
|
||||
data: { membershipAt: new Date(Date.now() - 120_000) },
|
||||
});
|
||||
const fresh = await get(
|
||||
'brokerage-accounts/all/portfolio?sync=observe',
|
||||
'brokerage-accounts/all/portfolio',
|
||||
).expect(200);
|
||||
expect((fresh.body as PortfolioResourceDto).meta.freshness).toBe('fresh');
|
||||
expect((fresh.body as PortfolioResourceDto).data).toMatchObject({
|
||||
@@ -580,7 +580,7 @@ describe('local accounts and portfolio HTTP (SQLite)', () => {
|
||||
data: { membershipAt: new Date(Date.now() - 301_000) },
|
||||
});
|
||||
const stale = await get(
|
||||
'brokerage-accounts/all/portfolio?sync=observe',
|
||||
'brokerage-accounts/all/portfolio',
|
||||
).expect(200);
|
||||
expect((stale.body as PortfolioResourceDto).meta.freshness).toBe('fresh');
|
||||
expect((stale.body as PortfolioResourceDto).data?.isStale).toBe(false);
|
||||
@@ -595,7 +595,7 @@ describe('local accounts and portfolio HTTP (SQLite)', () => {
|
||||
await prisma.tbankConnection.updateMany({
|
||||
data: { membershipAt: new Date() },
|
||||
});
|
||||
const empty = await get('brokerage-accounts?sync=observe').expect(200);
|
||||
const empty = await get('brokerage-accounts').expect(200);
|
||||
expect((empty.body as BrokerageAccountsResourceDto).data).toEqual([]);
|
||||
expect((empty.body as BrokerageAccountsResourceDto).meta.availability).toBe(
|
||||
'available',
|
||||
@@ -625,7 +625,7 @@ describe('local accounts and portfolio HTTP (SQLite)', () => {
|
||||
await late.done;
|
||||
expect(await prisma.tbankPortfolio.count()).toBe(0);
|
||||
const replaced = await get(
|
||||
'brokerage-accounts/account/portfolio?sync=observe',
|
||||
'brokerage-accounts/account/portfolio',
|
||||
).expect(200);
|
||||
expect((replaced.body as PortfolioResourceDto).data).toBeNull();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user