Files
medusa-store/packages/modules/tax/integration-tests/__tests__/index.spec.ts
Shahed Nasser 150aa50397 feat(tax,types): Add method to retrieve a Tax Module Provider's service (#13784)
## Summary

**What** — What changes are introduced in this PR?

Add a method in the Tax Module's servie to retrieve a provider by its ID.

**Why** — Why are these changes relevant or necessary?  

The Tax Module Provider could be used for use cases other than calculating tax lines. For example, Avalara supports importing products to manage product-specific taxes. However, it's not possible right now to listen to the `product.created` event and create the product in Avalara with its provider. Instead, you'll have to create a separate module that also connects to Avalara and resolve it in the subsriber.

This also matches the pattern in the Analytics Module, which allows retrieving the underlying provider.

**How** — How have these changes been implemented?

Add a `getProvider` method to the Tax Module's service and its interface.

**Testing** — How have these changes been tested, or how can the reviewer test the feature?

Added integration test for the method.

---

## Examples

Provide examples or code snippets that demonstrate how this feature works, or how it can be used in practice.  
This helps with documentation and ensures maintainers can quickly understand and verify the change.

```ts
const avalaraProvider = taxModuleService.getProvider("tp_avalara_avalara")
```

---

## Checklist

Please ensure the following before requesting a review:

- [x] I have added a **changeset** for this PR
    - Every non-breaking change should be marked as a **patch**
    - To add a changeset, run `yarn changeset` and follow the prompts
- [x] The changes are covered by relevant **tests**
- [x] I have verified the code works as intended locally
- [ ] I have linked the related issue(s) if applicable

---

## Additional Context

Add any additional context, related issues, or references that might help the reviewer understand this PR.
2025-10-20 16:18:48 +00:00

1189 lines
34 KiB
TypeScript

import { ITaxModuleService } from "@medusajs/framework/types"
import { Module, Modules, toMikroORMEntity } from "@medusajs/framework/utils"
import { moduleIntegrationTestRunner } from "@medusajs/test-utils"
import { TaxModuleService } from "@services"
import { setupTaxStructure } from "../utils/setup-tax-structure"
jest.setTimeout(30000)
moduleIntegrationTestRunner<ITaxModuleService>({
moduleName: Modules.TAX,
testSuite: ({ service }) => {
describe("TaxModuleService", function () {
it(`should export the appropriate linkable configuration`, () => {
const linkable = Module(toMikroORMEntity(Modules.TAX), {
service: TaxModuleService,
}).linkable
expect(Object.keys(linkable)).toEqual([
"taxRate",
"taxRegion",
"taxRateRule",
"taxProvider",
])
Object.keys(linkable).forEach((key) => {
delete linkable[key].toJSON
})
expect(linkable).toEqual({
taxRate: {
id: {
linkable: "tax_rate_id",
entity: "TaxRate",
primaryKey: "id",
serviceName: "tax",
field: "taxRate",
},
},
taxRegion: {
id: {
linkable: "tax_region_id",
entity: "TaxRegion",
primaryKey: "id",
serviceName: "tax",
field: "taxRegion",
},
},
taxRateRule: {
id: {
linkable: "tax_rate_rule_id",
entity: "TaxRateRule",
primaryKey: "id",
serviceName: "tax",
field: "taxRateRule",
},
},
taxProvider: {
id: {
linkable: "tax_provider_id",
entity: "TaxProvider",
primaryKey: "id",
serviceName: "tax",
field: "taxProvider",
},
},
})
})
it("should create tax region", async () => {
const region = await service.createTaxRegions({
country_code: "US",
default_tax_rate: {
name: "Test Rate",
rate: 0.2,
code: "TEST",
},
})
expect(region).toEqual(
expect.objectContaining({
id: region.id,
country_code: "us",
})
)
})
it("should create two tax regions with the same country code but different province", async () => {
const regionOne = await service.createTaxRegions({
country_code: "US",
province_code: "CA",
default_tax_rate: {
name: "Test Rate",
rate: 0.2,
code: "TEST",
},
})
const regionTwo = await service.createTaxRegions({
country_code: "US",
province_code: "NY",
default_tax_rate: {
name: "Test Rate",
rate: 0.2,
code: "TEST",
},
})
expect(regionOne).toEqual(
expect.objectContaining({
id: regionOne.id,
country_code: "us",
province_code: "ca",
})
)
expect(regionTwo).toEqual(
expect.objectContaining({
id: regionTwo.id,
country_code: "us",
province_code: "ny",
})
)
})
it("should create two tax regions in a child-parent-like relationship", async () => {
const regionOne = await service.createTaxRegions({
country_code: "US",
default_tax_rate: {
name: "Test Rate",
rate: 0.2,
code: "TEST",
},
})
const regionTwo = await service.createTaxRegions({
country_code: "US",
parent_id: regionOne.id,
province_code: "NY",
default_tax_rate: {
name: "Test Rate",
rate: 0.2,
code: "TEST",
},
})
expect(regionOne).toEqual(
expect.objectContaining({
id: regionOne.id,
country_code: "us",
province_code: null,
})
)
expect(regionTwo).toEqual(
expect.objectContaining({
id: regionTwo.id,
country_code: "us",
province_code: "ny",
})
)
})
it("should create three tax regions in a child-parent-like relationship", async () => {
const regionOne = await service.createTaxRegions({
country_code: "US",
default_tax_rate: {
name: "Test Rate",
rate: 0.2,
code: "TEST",
},
})
const regionTwo = await service.createTaxRegions({
country_code: "US",
parent_id: regionOne.id,
province_code: "NY",
default_tax_rate: {
name: "Test Rate",
rate: 0.2,
code: "TEST",
},
})
const regionThree = await service.createTaxRegions({
country_code: "US",
parent_id: regionOne.id,
province_code: "NE",
default_tax_rate: {
name: "Test Rate",
rate: 0.2,
code: "TEST",
},
})
expect(regionOne).toEqual(
expect.objectContaining({
id: regionOne.id,
country_code: "us",
province_code: null,
})
)
expect(regionTwo).toEqual(
expect.objectContaining({
id: regionTwo.id,
country_code: "us",
province_code: "ny",
})
)
expect(regionThree).toEqual(
expect.objectContaining({
id: regionThree.id,
country_code: "us",
province_code: "ne",
})
)
})
it("should throw when creating a tax region with a country code of an existing region", async () => {
await service.createTaxRegions({
country_code: "US",
default_tax_rate: {
name: "Test Rate",
rate: 0.2,
code: "TEST",
},
})
const error = await service
.createTaxRegions({
country_code: "US",
default_tax_rate: {
name: "Test Rate",
rate: 0.2,
code: "TEST",
},
})
.catch((e) => e)
expect(error.message).toEqual(
"Tax region with country_code: us, already exists."
)
})
it("should throw when creating a tax region with a country code and province code of an existing region", async () => {
await service.createTaxRegions({
country_code: "US",
province_code: "CA",
default_tax_rate: {
name: "Test Rate",
rate: 0.2,
code: "TEST",
},
})
const error = await service
.createTaxRegions({
country_code: "US",
province_code: "CA",
default_tax_rate: {
name: "Test Rate",
rate: 0.2,
code: "TEST",
},
})
.catch((e) => e)
expect(error.message).toEqual(
"Tax region with country_code: us, province_code: ca, already exists."
)
})
it("should create tax rates and update them", async () => {
const region = await service.createTaxRegions({
country_code: "US",
default_tax_rate: {
name: "Test Rate",
rate: 0.2,
code: "TEST-CODE",
},
})
const rate = await service.createTaxRates({
tax_region_id: region.id,
name: "Shipping Rate",
code: "test",
rate: 8.23,
})
const updatedRate = await service.updateTaxRates(rate.id, {
name: "Updated Rate",
code: "TEST",
rate: 8.25,
})
expect(updatedRate).toEqual(
expect.objectContaining({
tax_region_id: region.id,
rate: 8.25,
name: "Updated Rate",
code: "TEST",
is_default: false,
})
)
const updatedDefaultRate = await service.updateTaxRates(
{ tax_region_id: region.id, is_default: true },
{ rate: 2 }
)
expect(updatedDefaultRate).toEqual([
expect.objectContaining({
tax_region_id: region.id,
rate: 2,
name: "Test Rate",
code: "TEST-CODE",
is_default: true,
}),
])
const rates = await service.listTaxRates()
expect(rates).toEqual(
expect.arrayContaining([
expect.objectContaining({
tax_region_id: region.id,
rate: 2,
name: "Test Rate",
code: "TEST-CODE",
is_default: true,
}),
expect.objectContaining({
tax_region_id: region.id,
rate: 8.25,
name: "Updated Rate",
code: "TEST",
is_default: false,
}),
])
)
})
it("should update tax rates with rules", async () => {
const region = await service.createTaxRegions({
country_code: "US",
default_tax_rate: {
name: "Test Rate",
rate: 0.2,
code: "TEST-CODE",
},
})
const rate = await service.createTaxRates({
tax_region_id: region.id,
name: "Shipping Rate",
code: "test",
rate: 8.23,
})
await service.updateTaxRates(rate.id, {
name: "Updated Rate",
code: "TEST",
rate: 8.25,
rules: [
{ reference: "product", reference_id: "product_id_1" },
{ reference: "product_type", reference_id: "product_type_id" },
],
})
const rules = await service.listTaxRateRules({ tax_rate_id: rate.id })
expect(rules).toEqual(
expect.arrayContaining([
expect.objectContaining({
reference: "product",
reference_id: "product_id_1",
}),
expect.objectContaining({
reference: "product_type",
reference_id: "product_type_id",
}),
])
)
await service.updateTaxRates(rate.id, {
rules: [
{ reference: "product", reference_id: "product_id_1" },
{ reference: "product", reference_id: "product_id_2" },
{ reference: "product_type", reference_id: "product_type_id_2" },
{ reference: "product_type", reference_id: "product_type_id_3" },
],
})
const rulesWithDeletes = await service.listTaxRateRules(
{ tax_rate_id: rate.id },
{ withDeleted: true }
)
expect(rulesWithDeletes).toEqual(
expect.arrayContaining([
expect.objectContaining({
reference: "product",
reference_id: "product_id_2",
}),
expect.objectContaining({
reference: "product_type",
reference_id: "product_type_id_2",
}),
expect.objectContaining({
reference: "product_type",
reference_id: "product_type_id_3",
}),
expect.objectContaining({
reference: "product",
reference_id: "product_id_1",
deleted_at: expect.any(Date),
}),
expect.objectContaining({
reference: "product_type",
reference_id: "product_type_id",
deleted_at: expect.any(Date),
}),
])
)
})
it("should create a tax region", async () => {
const region = await service.createTaxRegions({
country_code: "US",
default_tax_rate: {
code: "TEST",
name: "Test Rate",
rate: 0.2,
},
})
const [provinceRegion] = await service.createTaxRegions([
{
country_code: "US",
province_code: "CA",
parent_id: region.id,
default_tax_rate: {
code: "TEST",
name: "CA Rate",
rate: 8.25,
},
},
])
const listedRegions = await service.listTaxRegions()
expect(listedRegions).toEqual(
expect.arrayContaining([
expect.objectContaining({
id: region.id,
country_code: "us",
province_code: null,
parent_id: null,
}),
expect.objectContaining({
id: provinceRegion.id,
country_code: "us",
province_code: "ca",
parent_id: region.id,
}),
])
)
const rates = await service.listTaxRates()
expect(rates).toEqual(
expect.arrayContaining([
expect.objectContaining({
tax_region_id: region.id,
rate: 0.2,
name: "Test Rate",
is_default: true,
}),
expect.objectContaining({
tax_region_id: provinceRegion.id,
rate: 8.25,
name: "CA Rate",
is_default: true,
}),
])
)
})
it("should create a tax rate rule", async () => {
const [region] = await service.createTaxRegions([
{
country_code: "US",
default_tax_rate: {
code: "TEST",
name: "Test Rate",
rate: 0.2,
},
},
])
const rate = await service.createTaxRates({
tax_region_id: region.id,
name: "Shipping Rate",
rate: 8.23,
code: "TEST-CODE",
})
await service.createTaxRateRules([
{
tax_rate_id: rate.id,
reference: "product",
reference_id: "prod_1234",
},
])
const listedRules = await service.listTaxRateRules(
{},
{
relations: ["tax_rate"],
}
)
expect(listedRules).toEqual(
expect.arrayContaining([
expect.objectContaining({
reference: "product",
reference_id: "prod_1234",
tax_rate: expect.objectContaining({
tax_region_id: region.id,
name: "Shipping Rate",
rate: 8.23,
}),
}),
])
)
})
it("applies specific product rules at the province level", async () => {
await setupTaxStructure(service)
const item = {
id: "item_test",
product_id: "product_id_1", // Matching the specific product rate for CA province
quantity: 1,
}
const calculationContext = {
address: {
country_code: "US",
province_code: "CA",
},
}
const taxLines = await service.getTaxLines([item], calculationContext)
expect(taxLines).toEqual([
expect.objectContaining({
rate_id: expect.any(String),
rate: 3, // Expecting the reduced rate for specific products in CA
code: "CAREDUCE_PROD",
name: "CA Reduced Rate for Products",
}),
])
})
it("applies specific product type rules at the province level", async () => {
await setupTaxStructure(service)
const item = {
id: "item_test",
product_id: "product_id_unknown", // This product does not have a specific rule
product_type_id: "product_type_id_1", // Matching the specific product type rate for CA province
quantity: 1,
}
const calculationContext = {
address: {
country_code: "US",
province_code: "CA",
},
}
const taxLines = await service.getTaxLines([item], calculationContext)
expect(taxLines).toEqual([
expect.objectContaining({
rate_id: expect.any(String),
rate: 1, // Expecting the reduced rate for specific product types in CA
code: "CAREDUCE_TYPE",
name: "CA Reduced Rate for Product Type",
}),
])
})
it("applies specific product type rules at the province level", async () => {
await setupTaxStructure(service)
const item = {
id: "item_test",
product_id: "product_id_unknown", // This product does not have a specific rule
product_type_id: "product_type_id_1", // Matching the specific product type rate for CA province
quantity: 1,
}
const calculationContext = {
address: {
country_code: "US",
province_code: "CA",
},
}
const taxLines = await service.getTaxLines([item], calculationContext)
expect(taxLines).toEqual([
expect.objectContaining({
rate_id: expect.any(String),
rate: 1, // Expecting the reduced rate for specific product types in CA
code: "CAREDUCE_TYPE",
name: "CA Reduced Rate for Product Type",
}),
])
})
it("applies default province rules when no specific product or product type rule matches", async () => {
await setupTaxStructure(service)
const item = {
id: "item_test",
product_id: "product_id_unknown",
quantity: 1,
}
const calculationContext = {
address: {
country_code: "US",
province_code: "NY", // Testing with NY to apply the default provincial rate
},
}
const taxLines = await service.getTaxLines([item], calculationContext)
expect(taxLines).toEqual([
expect.objectContaining({
rate_id: expect.any(String),
rate: 6, // Expecting the default rate for NY province
code: "NYDEFAULT",
name: "NY Default Rate",
}),
])
})
it("applies specific product rules at the country level when no province rate applies", async () => {
await setupTaxStructure(service)
const item = {
id: "item_test",
product_id: "product_id_4", // Assuming this ID now has a specific rule at the country level for Canada
quantity: 1,
}
const calculationContext = {
address: {
country_code: "CA",
province_code: "ON", // This province does not have a specific rule
},
}
const taxLines = await service.getTaxLines([item], calculationContext)
expect(taxLines).toEqual([
expect.objectContaining({
rate_id: expect.any(String),
rate: 3, // Expecting the reduced rate for specific products in Canada
code: "CAREDUCE_PROD_CA",
name: "Canada Reduced Rate for Product",
}),
])
})
it("applies default country rules when no specific product or product type rule matches", async () => {
await setupTaxStructure(service)
const item = {
id: "item_test",
product_id: "product_id_unknown",
quantity: 1,
}
const calculationContext = {
address: {
country_code: "DE", // Testing with Germany to apply the default country rate
},
}
const taxLines = await service.getTaxLines([item], calculationContext)
expect(taxLines).toEqual([
expect.objectContaining({
rate_id: expect.any(String),
rate: 19,
code: "DE19",
name: "Germany Default Rate",
}),
])
})
it("prioritizes specific product rules over product type rules", async () => {
await setupTaxStructure(service)
const item = {
id: "item_test",
product_id: "product_id_1", // This product has a specific rule for product type and product
product_type_id: "product_type_id_1", // This product type has a specific rule for product type
quantity: 1,
}
const calculationContext = {
address: {
country_code: "US",
province_code: "CA",
},
}
const taxLines = await service.getTaxLines([item], calculationContext)
expect(taxLines).toEqual([
expect.objectContaining({
rate_id: expect.any(String),
rate: 3, // Expecting the reduced rate for specific products in CA
code: "CAREDUCE_PROD",
name: "CA Reduced Rate for Products",
}),
])
})
it("prioritizes specific shipping rate over default rate", async () => {
const region = await service.createTaxRegions({
country_code: "US",
provider_id: "tp_system",
default_tax_rate: {
code: "TEST",
name: "Test Rate",
rate: 5,
},
})
const rate = await service.createTaxRates({
tax_region_id: region.id,
name: "Shipping Rate",
code: "SHIPPING_TEST",
rate: 2,
})
const item = {
id: "shipping_test",
shipping_option_id: "so_1234",
quantity: 1,
}
const calculationContext = {
address: {
country_code: "US",
},
}
let taxLines = await service.getTaxLines([item], calculationContext)
expect(taxLines).toEqual([
expect.objectContaining({
rate_id: expect.any(String),
rate: 5,
code: "TEST",
name: "Test Rate",
}),
])
await service.updateTaxRates(rate.id, {
rules: [
{
reference: "shipping_option",
reference_id: "so_1234",
},
],
})
taxLines = await service.getTaxLines([item], calculationContext)
expect(taxLines).toEqual([
expect.objectContaining({
rate_id: expect.any(String),
rate: 2,
code: "SHIPPING_TEST",
name: "Shipping Rate",
}),
])
})
it("should delete tax rate", async () => {
const region = await service.createTaxRegions({
country_code: "US",
})
const taxRate = await service.createTaxRates({
tax_region_id: region.id,
value: 10,
code: "test",
name: "test",
})
await service.deleteTaxRates(taxRate.id)
const rates = await service.listTaxRates({ tax_region_id: region.id })
expect(rates).toEqual([])
})
it("should soft delete tax rate", async () => {
const region = await service.createTaxRegions({
country_code: "US",
})
const taxRate = await service.createTaxRates({
tax_region_id: region.id,
value: 10,
code: "test",
name: "test",
})
await service.softDeleteTaxRates([taxRate.id])
const rates = await service.listTaxRates(
{ tax_region_id: region.id },
{ withDeleted: true }
)
expect(rates).toEqual([
expect.objectContaining({
id: taxRate.id,
deleted_at: expect.any(Date),
}),
])
})
it("should delete a tax region and its rates", async () => {
const region = await service.createTaxRegions({
country_code: "US",
default_tax_rate: {
value: 2,
code: "test",
name: "default test",
},
})
await service.createTaxRates({
tax_region_id: region.id,
value: 10,
code: "test",
name: "test",
})
await service.deleteTaxRegions(region.id)
const taxRegions = await service.listTaxRegions()
const rates = await service.listTaxRates()
expect(taxRegions).toEqual([])
expect(rates).toEqual([])
})
it("should soft delete a tax region and its rates", async () => {
const region = await service.createTaxRegions({
country_code: "US",
default_tax_rate: {
value: 2,
code: "test",
name: "default test",
},
})
await service.createTaxRates({
tax_region_id: region.id,
value: 10,
code: "test",
name: "test",
})
await service.softDeleteTaxRegions([region.id])
const taxRegions = await service.listTaxRegions(
{},
{ withDeleted: true }
)
const rates = await service.listTaxRates({}, { withDeleted: true })
expect(taxRegions).toEqual([
expect.objectContaining({
id: region.id,
country_code: "us",
deleted_at: expect.any(Date),
}),
])
expect(rates).toEqual([
expect.objectContaining({
deleted_at: expect.any(Date),
}),
expect.objectContaining({
deleted_at: expect.any(Date),
}),
])
})
it("should delete a tax rate and its rules", async () => {
const region = await service.createTaxRegions({
country_code: "US",
})
const rate = await service.createTaxRates({
tax_region_id: region.id,
value: 10,
code: "test",
name: "test",
rules: [
{ reference: "product", reference_id: "product_id_1" },
{ reference: "product_type", reference_id: "product_type_id" },
],
})
await service.deleteTaxRates(rate.id)
const taxRegions = await service.listTaxRegions()
const rates = await service.listTaxRates()
const rules = await service.listTaxRateRules()
expect(taxRegions).toEqual([expect.objectContaining({ id: region.id })])
expect(rates).toEqual([])
expect(rules).toEqual([])
})
it("should soft delete a tax rate and its rules", async () => {
const region = await service.createTaxRegions({
country_code: "US",
})
const rate = await service.createTaxRates({
tax_region_id: region.id,
value: 10,
code: "test",
name: "test",
rules: [
{ reference: "product", reference_id: "product_id_1" },
{ reference: "product_type", reference_id: "product_type_id" },
],
})
await service.softDeleteTaxRates(rate.id)
const taxRegions = await service.listTaxRegions(
{},
{ withDeleted: true }
)
const rates = await service.listTaxRates({}, { withDeleted: true })
const rules = await service.listTaxRateRules({}, { withDeleted: true })
expect(taxRegions).toEqual([
expect.objectContaining({ id: region.id, deleted_at: null }),
])
expect(rates).toEqual([
expect.objectContaining({
id: rate.id,
deleted_at: expect.any(Date),
}),
])
expect(rules).toEqual([
expect.objectContaining({
tax_rate_id: rate.id,
deleted_at: expect.any(Date),
}),
expect.objectContaining({
tax_rate_id: rate.id,
deleted_at: expect.any(Date),
}),
])
})
it("should soft delete a tax rule", async () => {
const region = await service.createTaxRegions({
country_code: "US",
})
const rate = await service.createTaxRates({
tax_region_id: region.id,
value: 10,
code: "test",
name: "test",
})
const [ruleOne, ruleTwo] = await service.createTaxRateRules([
{
tax_rate_id: rate.id,
reference: "product",
reference_id: "product_id_1",
},
{
tax_rate_id: rate.id,
reference: "product_type",
reference_id: "product_type_id",
},
])
await service.softDeleteTaxRateRules([ruleOne.id])
const rules = await service.listTaxRateRules({}, { withDeleted: true })
expect(rules).toEqual(
expect.arrayContaining([
expect.objectContaining({
id: ruleOne.id,
deleted_at: expect.any(Date),
}),
expect.objectContaining({
id: ruleTwo.id,
deleted_at: null,
}),
])
)
const rateWithRules = await service.retrieveTaxRate(rate.id, {
relations: ["rules"],
})
expect(rateWithRules.rules.length).toBe(1)
// should be possible to add the rule back again
await service.createTaxRateRules({
tax_rate_id: rate.id,
reference: ruleOne.reference,
reference_id: ruleOne.reference_id,
})
const rateWithRulesAfterReAdd = await service.retrieveTaxRate(rate.id, {
relations: ["rules"],
})
expect(rateWithRulesAfterReAdd.rules.length).toBe(2)
})
it("should fail on duplicate rules", async () => {
const region = await service.createTaxRegions({
country_code: "US",
})
await expect(
service.createTaxRates({
tax_region_id: region.id,
value: 10,
code: "test",
name: "test",
rules: [
{ reference: "product", reference_id: "product_id_1" },
{ reference: "product", reference_id: "product_id_1" },
],
})
).rejects.toThrowError(
/Tax rate rule with tax_rate_id: .*?, reference_id: product_id_1, already exists./
)
const rate = await service.createTaxRates({
tax_region_id: region.id,
value: 10,
code: "test",
name: "test",
rules: [{ reference: "product", reference_id: "product_id_1" }],
})
await expect(
service.createTaxRateRules({
tax_rate_id: rate.id,
reference: "product",
reference_id: "product_id_1",
})
).rejects.toThrowError(
/Tax rate rule with tax_rate_id: .*?, reference_id: product_id_1, already exists./
)
})
it("should fail to create province region belonging to a parent with non-matching country", async () => {
const caRegion = await service.createTaxRegions({
country_code: "CA",
})
await expect(
service.createTaxRegions({
country_code: "US", // This should be CA
parent_id: caRegion.id,
province_code: "QC",
})
).rejects.toThrowError(
`Province region must belong to a parent region with the same country code. You are trying to create a province region with (country: us, province: qc) but parent expects (country: ca)`
)
})
it("should fail duplicate regions", async () => {
await service.createTaxRegions({
country_code: "CA",
})
await service.createTaxRegions({
country_code: "CA",
province_code: "QC",
})
await expect(
service.createTaxRegions({
country_code: "CA",
province_code: "QC",
})
).rejects.toThrowError(
"Tax region with country_code: ca, province_code: qc, already exists."
)
})
it("should fail to create region with non-existing parent", async () => {
await expect(
service.createTaxRegions({
parent_id: "something random",
country_code: "CA",
province_code: "QC",
})
).rejects.toThrowError(
`Province region must belong to a parent region. You are trying to create a province region with (country: ca, province: qc) but parent does not exist`
)
})
it("should fail to create two default tax rates", async () => {
const rate = await service.createTaxRegions({
country_code: "CA",
default_tax_rate: {
name: "Test Rate",
rate: 0.2,
code: "TEST-CODE",
},
})
await expect(
service.createTaxRates({
tax_region_id: rate.id,
name: "Shipping Rate",
rate: 8.23,
is_default: true,
code: "TEST-CODE-2",
})
).rejects.toThrowError(
/Tax rate with tax_region_id: .*?, already exists./
)
})
it("should delete all child regions when parent region is deleted", async () => {
const region = await service.createTaxRegions({
country_code: "CA",
})
const provinceRegion = await service.createTaxRegions({
parent_id: region.id,
country_code: "CA",
province_code: "QC",
})
await service.deleteTaxRegions(region.id)
const taxRegions = await service.listTaxRegions({
id: provinceRegion.id,
})
expect(taxRegions).toEqual([])
})
it("should soft delete all child regions when parent region is deleted", async () => {
const region = await service.createTaxRegions({
country_code: "CA",
})
const provinceRegion = await service.createTaxRegions({
parent_id: region.id,
country_code: "CA",
province_code: "QC",
})
await service.softDeleteTaxRegions([region.id])
const taxRegions = await service.listTaxRegions(
{ id: provinceRegion.id },
{ withDeleted: true }
)
expect(taxRegions).toEqual([
expect.objectContaining({
id: provinceRegion.id,
deleted_at: expect.any(Date),
}),
])
})
it("should retrieve a tax module provider's service", async () => {
const providerService = service.getProvider("tp_system")
expect(providerService).toBeDefined()
expect(providerService.getIdentifier()).toEqual("system")
})
})
},
})