Skip to content

Commit e4c81cf

Browse files
authored
Merge branch 'main' into soft-delete-user
2 parents b0ad2df + 080116e commit e4c81cf

File tree

4 files changed

+153
-7
lines changed

4 files changed

+153
-7
lines changed

__tests__/paddle.ts

Lines changed: 139 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import {
3434
DEFAULT_CORES_METADATA,
3535
PricingType,
3636
} from '../src/common/paddle/pricing';
37+
import { CountryCode, CurrencyCode } from '@paddle/paddle-node-sdk';
3738

3839
let app: FastifyInstance;
3940
let con: DataSource;
@@ -45,7 +46,7 @@ beforeAll(async () => {
4546
con = await createOrGetConnection();
4647
app = await appFunc();
4748
state = await initializeGraphQLTesting(
48-
() => new MockContext(con, loggedUser),
49+
() => new MockContext(con, loggedUser || undefined),
4950
);
5051
client = state.client;
5152
return app.ready();
@@ -371,8 +372,8 @@ describe('plus pricing metadata', () => {
371372

372373
describe('plus pricing preview', () => {
373374
const QUERY = /* GraphQL */ `
374-
query PricingPreview($type: PricingType) {
375-
pricingPreview(type: $type) {
375+
query PricingPreview($type: PricingType, $locale: String) {
376+
pricingPreview(type: $type, locale: $locale) {
376377
metadata {
377378
appsId
378379
title
@@ -562,6 +563,141 @@ describe('plus pricing preview', () => {
562563

563564
expect(result).toEqual(result2);
564565
});
566+
567+
it('should format prices according to locale', async () => {
568+
loggedUser = 'whp-1';
569+
const mockPreview = {
570+
customerId: '1',
571+
addressId: '1',
572+
businessId: null,
573+
discountId: null,
574+
address: {
575+
countryCode: 'DE' as CountryCode,
576+
postalCode: '12345',
577+
},
578+
customerIpAddress: '127.0.0.1',
579+
availablePaymentMethods: ['card' as const],
580+
details: {
581+
lineItems: [
582+
{
583+
price: {
584+
id: 'pri_monthly',
585+
productId: 'prod_123',
586+
name: 'Monthly Subscription',
587+
description: 'Monthly subscription for Daily.dev Plus',
588+
type: 'standard' as const,
589+
status: 'active' as const,
590+
quantity: {
591+
minimum: 1,
592+
maximum: 1,
593+
},
594+
customData: {
595+
label: 'Monthly',
596+
appsId: 'monthly-sub',
597+
},
598+
billingCycle: {
599+
interval: 'month' as const,
600+
frequency: 1,
601+
},
602+
trialPeriod: null,
603+
unitPrice: {
604+
amount: '5.00',
605+
currencyCode: 'EUR' as CurrencyCode,
606+
},
607+
unitPriceOverrides: [],
608+
taxMode: 'internal' as const,
609+
productTaxCategory: 'standard',
610+
createdAt: new Date().toISOString(),
611+
updatedAt: new Date().toISOString(),
612+
importMeta: null,
613+
product: {
614+
id: 'prod_123',
615+
name: 'Daily.dev Plus',
616+
description: 'Daily.dev Plus Subscription',
617+
type: 'standard' as const,
618+
taxCategory: 'standard' as const,
619+
imageUrl: 'https://daily.dev/plus.png',
620+
customData: {},
621+
status: 'active' as const,
622+
createdAt: new Date().toISOString(),
623+
updatedAt: new Date().toISOString(),
624+
importMeta: null,
625+
prices: [],
626+
},
627+
},
628+
product: {
629+
id: 'prod_123',
630+
name: 'Daily.dev Plus',
631+
description: 'Daily.dev Plus Subscription',
632+
type: 'standard' as const,
633+
taxCategory: 'standard' as const,
634+
imageUrl: 'https://daily.dev/plus.png',
635+
customData: {},
636+
status: 'active' as const,
637+
createdAt: new Date().toISOString(),
638+
updatedAt: new Date().toISOString(),
639+
importMeta: null,
640+
prices: [],
641+
},
642+
quantity: 1,
643+
taxRate: '0.00',
644+
unitTotals: {
645+
subtotal: '5.00',
646+
discount: '0.00',
647+
tax: '0.00',
648+
total: '5.00',
649+
},
650+
formattedUnitTotals: {
651+
subtotal: '€5,00',
652+
discount: '€0,00',
653+
tax: '€0,00',
654+
total: '€5,00',
655+
},
656+
formattedTotals: {
657+
subtotal: '€5,00',
658+
discount: '€0,00',
659+
tax: '€0,00',
660+
total: '€5,00',
661+
},
662+
totals: {
663+
subtotal: '5.00',
664+
discount: '0.00',
665+
tax: '0.00',
666+
total: '5.00',
667+
},
668+
discounts: [],
669+
},
670+
],
671+
},
672+
currencyCode: 'EUR' as CurrencyCode,
673+
};
674+
675+
jest
676+
.spyOn(paddleInstance.pricingPreview, 'preview')
677+
.mockResolvedValue(mockPreview as never);
678+
679+
const result = await client.query(QUERY, {
680+
variables: {
681+
type: PricingType.Plus,
682+
locale: 'de-DE',
683+
},
684+
});
685+
expect(result.data.pricingPreview).toHaveLength(1);
686+
const preview = result.data.pricingPreview[0];
687+
expect(preview.price.formatted).toBe('€5,00');
688+
});
689+
690+
it('should use default locale when not specified', async () => {
691+
loggedUser = 'whp-1';
692+
const result = await client.query(QUERY, {
693+
variables: {
694+
type: PricingType.Plus,
695+
},
696+
});
697+
expect(result.data.pricingPreview).toHaveLength(1);
698+
const preview = result.data.pricingPreview[0];
699+
expect(preview.price.formatted).toBe('$5.00');
700+
});
565701
});
566702

567703
describe('plus subscription', () => {

src/entity/posts/Post.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,13 @@ export type PostFlags = Partial<{
4343
promoteToPublic: number | null;
4444
deletedBy: string;
4545
vordr: boolean;
46+
coverVideo: string;
4647
}>;
4748

48-
export type PostFlagsPublic = Pick<PostFlags, 'private' | 'promoteToPublic'>;
49+
export type PostFlagsPublic = Pick<
50+
PostFlags,
51+
'private' | 'promoteToPublic' | 'coverVideo'
52+
>;
4953

5054
export type PostContentQuality = Partial<{
5155
is_ai_probability: number;

src/schema/paddle.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ export const typeDefs = /* GraphQL */ `
131131
pricePreviews: PricePreviews! @auth
132132
corePricePreviews: PricePreviews! @auth
133133
pricingMetadata(type: PricingType): [ProductPricingMetadata!]! @auth
134-
pricingPreview(type: PricingType): [ProductPricingPreview!]! @auth
134+
pricingPreview(type: PricingType, locale: String): [ProductPricingPreview!]!
135135
}
136136
137137
${toGQLEnum(PricingType, 'PricingType')}
@@ -275,6 +275,7 @@ export interface GQLCustomData {
275275

276276
interface PaddlePricingPreviewArgs {
277277
type?: PricingType;
278+
locale?: string;
278279
}
279280

280281
export const resolvers: IResolvers<unknown, AuthContext> = traceResolvers<
@@ -389,7 +390,7 @@ export const resolvers: IResolvers<unknown, AuthContext> = traceResolvers<
389390
): Promise<BasePricingMetadata[]> => getPricingMetadata(ctx, type),
390391
pricingPreview: async (
391392
_,
392-
{ type = PricingType.Plus }: PaddlePricingPreviewArgs,
393+
{ type = PricingType.Plus, locale }: PaddlePricingPreviewArgs,
393394
ctx,
394395
): Promise<BasePricingPreview[]> => {
395396
const metadata = await getPricingMetadata(ctx, type);
@@ -416,7 +417,7 @@ export const resolvers: IResolvers<unknown, AuthContext> = traceResolvers<
416417
return {
417418
metadata: meta,
418419
priceId: item.price.id,
419-
price: getProductPrice(item),
420+
price: getProductPrice(item, locale),
420421
currency: {
421422
code: preview.currencyCode,
422423
symbol: removeNumbers(item.formattedTotals.total),

src/schema/posts.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,11 @@ export const typeDefs = /* GraphQL */ `
360360
The unix timestamp (seconds) the post will be promoted to public to
361361
"""
362362
promoteToPublic: Int @auth(requires: [MODERATOR])
363+
364+
"""
365+
Cover video
366+
"""
367+
coverVideo: String
363368
}
364369
365370
type UserPostFlagsPublic {

0 commit comments

Comments
 (0)