fix: ILIKE operator not supported in sqlite (#393)

* fix: replace ILIKE operator with ILike function where possible

* remove: unused import

* fix: remove alias from test case as it is not needed

* fix: product variant query

* add: integration tests + fallback to original query for all queries searching on the display_id field

* remove: console.log
This commit is contained in:
Zakaria El Asri
2021-09-21 11:15:33 +02:00
committed by GitHub
parent 00ab03f3a2
commit 49a132976d
12 changed files with 793 additions and 448 deletions
@@ -1,50 +1,50 @@
const { dropDatabase } = require("pg-god");
const path = require("path");
const { dropDatabase } = require("pg-god")
const path = require("path")
const setupServer = require("../../../helpers/setup-server");
const { useApi } = require("../../../helpers/use-api");
const { useDb, initDb } = require("../../../helpers/use-db");
const setupServer = require("../../../helpers/setup-server")
const { useApi } = require("../../../helpers/use-api")
const { useDb, initDb } = require("../../../helpers/use-db")
const customerSeeder = require("../../helpers/customer-seeder");
const adminSeeder = require("../../helpers/admin-seeder");
const customerSeeder = require("../../helpers/customer-seeder")
const adminSeeder = require("../../helpers/admin-seeder")
jest.setTimeout(30000);
jest.setTimeout(30000)
describe("/admin/customers", () => {
let medusaProcess;
let dbConnection;
let medusaProcess
let dbConnection
beforeAll(async () => {
const cwd = path.resolve(path.join(__dirname, "..", ".."));
dbConnection = await initDb({ cwd });
medusaProcess = await setupServer({ cwd });
});
const cwd = path.resolve(path.join(__dirname, "..", ".."))
dbConnection = await initDb({ cwd })
medusaProcess = await setupServer({ cwd })
})
afterAll(async () => {
const db = useDb();
await db.shutdown();
const db = useDb()
await db.shutdown()
medusaProcess.kill();
});
medusaProcess.kill()
})
describe("GET /admin/customers", () => {
beforeEach(async () => {
try {
await adminSeeder(dbConnection);
await customerSeeder(dbConnection);
await adminSeeder(dbConnection)
await customerSeeder(dbConnection)
} catch (err) {
console.log(err);
throw err;
console.log(err)
throw err
}
});
})
afterEach(async () => {
const db = useDb();
await db.teardown();
});
const db = useDb()
await db.teardown()
})
it("lists customers and query count", async () => {
const api = useApi();
const api = useApi()
const response = await api
.get("/admin/customers", {
@@ -53,11 +53,11 @@ describe("/admin/customers", () => {
},
})
.catch((err) => {
console.log(err);
});
console.log(err)
})
expect(response.status).toEqual(200);
expect(response.data.count).toEqual(3);
expect(response.status).toEqual(200)
expect(response.data.count).toEqual(3)
expect(response.data.customers).toEqual(
expect.arrayContaining([
expect.objectContaining({
@@ -70,24 +70,24 @@ describe("/admin/customers", () => {
id: "test-customer-3",
}),
])
);
});
)
})
it("lists customers with specific query", async () => {
const api = useApi();
const api = useApi()
const response = await api
.get("/admin/customers?q=test2@email.com", {
.get("/admin/customers?q=est2@", {
headers: {
Authorization: "Bearer test_token",
},
})
.catch((err) => {
console.log(err);
});
console.log(err)
})
expect(response.status).toEqual(200);
expect(response.data.count).toEqual(1);
expect(response.status).toEqual(200)
expect(response.data.count).toEqual(1)
expect(response.data.customers).toEqual(
expect.arrayContaining([
expect.objectContaining({
@@ -95,11 +95,11 @@ describe("/admin/customers", () => {
email: "test2@email.com",
}),
])
);
});
)
})
it("lists customers with expand query", async () => {
const api = useApi();
const api = useApi()
const response = await api
.get("/admin/customers?q=test1@email.com&expand=shipping_addresses", {
@@ -108,11 +108,11 @@ describe("/admin/customers", () => {
},
})
.catch((err) => {
console.log(err);
});
console.log(err)
})
expect(response.status).toEqual(200);
expect(response.data.count).toEqual(1);
expect(response.status).toEqual(200)
expect(response.data.count).toEqual(1)
expect(response.data.customers).toEqual(
expect.arrayContaining([
expect.objectContaining({
@@ -126,7 +126,7 @@ describe("/admin/customers", () => {
]),
}),
])
);
});
});
});
)
})
})
})
@@ -24,6 +24,67 @@ describe("/admin/discounts", () => {
medusaProcess.kill()
})
describe("GET /admin/discounts", () => {
beforeEach(async () => {
const manager = dbConnection.manager
try {
await adminSeeder(dbConnection)
await manager.insert(DiscountRule, {
id: "test-discount-rule",
description: "Test discount rule",
type: "percentage",
value: 10,
allocation: "total",
})
await manager.insert(Discount, {
id: "test-discount",
code: "TESTING",
rule_id: "test-discount-rule",
is_dynamic: false,
is_disabled: false,
})
await manager.insert(Discount, {
id: "messi-discount",
code: "BARCA100",
rule_id: "test-discount-rule",
is_dynamic: false,
is_disabled: false,
})
} catch (err) {
throw err
}
})
afterEach(async () => {
const db = useDb()
await db.teardown()
})
it("should list discounts that match a specific query in a case insensitive manner", async () => {
const api = useApi()
const response = await api
.get("/admin/discounts?q=barca", {
headers: {
Authorization: "Bearer test_token",
},
})
.catch((err) => {
console.log(err)
})
expect(response.status).toEqual(200)
expect(response.data.count).toEqual(1)
expect(response.data.discounts).toEqual(
expect.arrayContaining([
expect.objectContaining({
id: "messi-discount",
code: "BARCA100",
}),
])
)
})
})
describe("POST /admin/discounts", () => {
beforeEach(async () => {
try {
@@ -1,54 +1,162 @@
const path = require("path");
const { Region } = require("@medusajs/medusa");
const path = require("path")
const { Region, GiftCard } = require("@medusajs/medusa")
const setupServer = require("../../../helpers/setup-server");
const { useApi } = require("../../../helpers/use-api");
const { initDb, useDb } = require("../../../helpers/use-db");
const adminSeeder = require("../../helpers/admin-seeder");
const setupServer = require("../../../helpers/setup-server")
const { useApi } = require("../../../helpers/use-api")
const { initDb, useDb } = require("../../../helpers/use-db")
const adminSeeder = require("../../helpers/admin-seeder")
jest.setTimeout(30000);
jest.setTimeout(30000)
describe("/admin/gift-cards", () => {
let medusaProcess;
let dbConnection;
let medusaProcess
let dbConnection
beforeAll(async () => {
const cwd = path.resolve(path.join(__dirname, "..", ".."));
dbConnection = await initDb({ cwd });
medusaProcess = await setupServer({ cwd });
});
const cwd = path.resolve(path.join(__dirname, "..", ".."))
dbConnection = await initDb({ cwd })
medusaProcess = await setupServer({ cwd })
})
afterAll(async () => {
const db = useDb();
await db.shutdown();
const db = useDb()
await db.shutdown()
medusaProcess.kill();
});
medusaProcess.kill()
})
describe("GET /admin/gift-cards", () => {
beforeEach(async () => {
const manager = dbConnection.manager
try {
await adminSeeder(dbConnection)
await manager.insert(Region, {
id: "test-region",
name: "Test Region",
currency_code: "usd",
tax_rate: 0,
})
await manager.insert(GiftCard, {
id: "gift_test",
code: "GC_TEST",
value: 20000,
balance: 20000,
region_id: "test-region",
})
await manager.insert(GiftCard, {
id: "another_gift_test",
code: "CARD_TEST",
value: 200000,
balance: 200000,
region_id: "test-region",
})
} catch (err) {
console.log(err)
throw err
}
})
afterEach(async () => {
const db = useDb()
await db.teardown()
})
it("lists gift cards and query count", async () => {
const api = useApi()
const response = await api
.get("/admin/gift-cards", {
headers: {
Authorization: "Bearer test_token",
},
})
.catch((err) => {
console.log(err)
})
expect(response.status).toEqual(200)
expect(response.data.gift_cards).toEqual(
expect.arrayContaining([
expect.objectContaining({
id: "gift_test",
code: "GC_TEST",
}),
expect.objectContaining({
id: "another_gift_test",
code: "CARD_TEST",
}),
])
)
})
it("lists gift cards with specific query", async () => {
const api = useApi()
const response = await api
.get("/admin/gift-cards?q=gc", {
headers: {
Authorization: "Bearer test_token",
},
})
.catch((err) => {
console.log(err)
})
expect(response.status).toEqual(200)
expect(response.data.gift_cards.length).toEqual(1)
expect(response.data.gift_cards).toEqual(
expect.arrayContaining([
expect.objectContaining({
id: "gift_test",
code: "GC_TEST",
}),
])
)
})
it("lists no gift cards on query for non-existing gift card code", async () => {
const api = useApi()
const response = await api
.get("/admin/gift-cards?q=bla", {
headers: {
Authorization: "Bearer test_token",
},
})
.catch((err) => {
console.log(err)
})
expect(response.status).toEqual(200)
expect(response.data.gift_cards.length).toEqual(0)
expect(response.data.gift_cards).toEqual([])
})
})
describe("POST /admin/gift-cards", () => {
beforeEach(async () => {
const manager = dbConnection.manager;
const manager = dbConnection.manager
try {
await adminSeeder(dbConnection);
await adminSeeder(dbConnection)
await manager.insert(Region, {
id: "region",
name: "Test Region",
currency_code: "usd",
tax_rate: 0,
});
})
} catch (err) {
console.log(err);
throw err;
console.log(err)
throw err
}
});
})
afterEach(async () => {
const db = useDb();
await db.teardown();
});
const db = useDb()
await db.teardown()
})
it("creates a gift card", async () => {
const api = useApi();
const api = useApi()
const response = await api
.post(
@@ -64,13 +172,13 @@ describe("/admin/gift-cards", () => {
}
)
.catch((err) => {
console.log(err);
});
console.log(err)
})
expect(response.status).toEqual(200);
expect(response.data.gift_card.value).toEqual(1000);
expect(response.data.gift_card.balance).toEqual(1000);
expect(response.data.gift_card.region_id).toEqual("region");
});
});
});
expect(response.status).toEqual(200)
expect(response.data.gift_card.value).toEqual(1000)
expect(response.data.gift_card.balance).toEqual(1000)
expect(response.data.gift_card.region_id).toEqual("region")
})
})
})
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,153 @@
const path = require("path")
const setupServer = require("../../../helpers/setup-server")
const { useApi } = require("../../../helpers/use-api")
const { initDb, useDb } = require("../../../helpers/use-db")
const adminSeeder = require("../../helpers/admin-seeder")
const productSeeder = require("../../helpers/product-seeder")
jest.setTimeout(30000)
describe("/admin/products", () => {
let medusaProcess
let dbConnection
beforeAll(async () => {
const cwd = path.resolve(path.join(__dirname, "..", ".."))
dbConnection = await initDb({ cwd })
medusaProcess = await setupServer({ cwd })
})
afterAll(async () => {
const db = useDb()
await db.shutdown()
medusaProcess.kill()
})
describe("GET /admin/product-variants", () => {
beforeEach(async () => {
try {
await productSeeder(dbConnection)
await adminSeeder(dbConnection)
} catch (err) {
console.log(err)
throw err
}
})
afterEach(async () => {
const db = useDb()
await db.teardown()
})
it("lists all product variants", async () => {
const api = useApi()
const response = await api
.get("/admin/variants/", {
headers: {
Authorization: "Bearer test_token",
},
})
.catch((err) => {
console.log(err)
})
expect(response.status).toEqual(200)
expect(response.data.variants).toEqual(
expect.arrayContaining([
expect.objectContaining(
{
id: "test-variant",
},
{
id: "test-variant_2",
},
{
id: "test-variant_1",
}
),
])
)
})
it("lists all product variants matching a specific sku", async () => {
const api = useApi()
const response = await api
.get("/admin/variants?q=sku2", {
headers: {
Authorization: "Bearer test_token",
},
})
.catch((err) => {
console.log(err)
})
expect(response.status).toEqual(200)
expect(response.data.variants.length).toEqual(1)
expect(response.data.variants).toEqual(
expect.arrayContaining([
expect.objectContaining({
sku: "test-sku2",
}),
])
)
})
it("lists all product variants matching a specific variant title", async () => {
const api = useApi()
const response = await api
.get("/admin/variants?q=rank (1)", {
headers: {
Authorization: "Bearer test_token",
},
})
.catch((err) => {
console.log(err)
})
expect(response.status).toEqual(200)
expect(response.data.variants.length).toEqual(1)
expect(response.data.variants).toEqual(
expect.arrayContaining([
expect.objectContaining({
id: "test-variant_1",
sku: "test-sku1",
}),
])
)
})
it("lists all product variants matching a specific product title", async () => {
const api = useApi()
const response = await api
.get("/admin/variants?q=Test product1", {
headers: {
Authorization: "Bearer test_token",
},
})
.catch((err) => {
console.log(err)
})
expect(response.status).toEqual(200)
expect(response.data.variants.length).toEqual(2)
expect(response.data.variants).toEqual(
expect.arrayContaining([
expect.objectContaining({
product_id: "test-product1",
id: "test-variant_3",
sku: "test-sku3",
}),
expect.objectContaining({
product_id: "test-product1",
id: "test-variant_4",
sku: "test-sku4",
}),
])
)
})
})
})
@@ -494,9 +494,6 @@ describe("DiscountService", () => {
expect(discountRepository.findAndCount).toHaveBeenCalledTimes(1)
expect(discountRepository.findAndCount).toHaveBeenCalledWith({
join: {
alias: "discount",
},
where: expect.anything(),
skip: 0,
take: 50,
+7 -11
View File
@@ -3,7 +3,7 @@ import Scrypt from "scrypt-kdf"
import _ from "lodash"
import { Validator, MedusaError } from "medusa-core-utils"
import { BaseService } from "medusa-interfaces"
import { Brackets } from "typeorm"
import { Brackets, ILike } from "typeorm"
/**
* Provides layer to manipulate customers.
@@ -149,9 +149,9 @@ class CustomerService extends BaseService {
qb.andWhere(
new Brackets(qb => {
qb.where(`email ILIKE :q`, { q: `%${q}%` })
.orWhere(`first_name ILIKE :q`, { q: `%${q}%` })
.orWhere(`last_name ILIKE :q`, { q: `%${q}%` })
qb.where({ email: ILike(`%${q}%`) })
.orWhere({ first_name: ILike(`%${q}%`) })
.orWhere({ last_name: ILike(`%${q}%`) })
})
)
}
@@ -183,18 +183,14 @@ class CustomerService extends BaseService {
delete where.first_name
delete where.last_name
query.join = {
alias: "customer",
}
query.where = qb => {
qb.where(where)
qb.andWhere(
new Brackets(qb => {
qb.where(`customer.first_name ILIKE :q`, { q: `%${q}%` })
.orWhere(`customer.last_name ILIKE :q`, { q: `%${q}%` })
.orWhere(`customer.email ILIKE :q`, { q: `%${q}%` })
qb.where({ email: ILike(`%${q}%`) })
.orWhere({ first_name: ILike(`%${q}%`) })
.orWhere({ last_name: ILike(`%${q}%`) })
})
)
}
+2 -6
View File
@@ -2,7 +2,7 @@ import _ from "lodash"
import randomize from "randomatic"
import { BaseService } from "medusa-interfaces"
import { Validator, MedusaError } from "medusa-core-utils"
import { Brackets } from "typeorm"
import { Brackets, ILike } from "typeorm"
/**
* Provides layer to manipulate discounts.
@@ -151,16 +151,12 @@ class DiscountService extends BaseService {
delete where.code
query.join = {
alias: "discount",
}
query.where = qb => {
qb.where(where)
qb.andWhere(
new Brackets(qb => {
qb.where(`discount.code ILIKE :q`, { q: `%${q}%` })
qb.where({ code: ILike(`%${q}%`) })
})
)
}
+1 -1
View File
@@ -1,7 +1,7 @@
import _ from "lodash"
import { BaseService } from "medusa-interfaces"
import { MedusaError } from "medusa-core-utils"
import { Brackets } from "typeorm"
import { Brackets, ILike } from "typeorm"
/**
* Handles draft orders
+3 -4
View File
@@ -1,8 +1,7 @@
import _ from "lodash"
import randomize from "randomatic"
import { BaseService } from "medusa-interfaces"
import { Brackets } from "typeorm"
import { MedusaError } from "medusa-core-utils"
import { BaseService } from "medusa-interfaces"
import randomize from "randomatic"
import { Brackets } from "typeorm"
/**
* Provides layer to manipulate gift cards.
+4 -3
View File
@@ -1,5 +1,4 @@
import _ from "lodash"
import { Validator, MedusaError } from "medusa-core-utils"
import { MedusaError, Validator } from "medusa-core-utils"
import { BaseService } from "medusa-interfaces"
import { Brackets } from "typeorm"
@@ -237,7 +236,9 @@ class OrderService extends BaseService {
qb.andWhere(
new Brackets(qb => {
qb.where(`shipping_address.first_name ILIKE :q`, { q: `%${q}%` })
qb.where(`shipping_address.first_name ILIKE :qfn`, {
qfn: `%${q}%`,
})
.orWhere(`order.email ILIKE :q`, { q: `%${q}%` })
.orWhere(`display_id::varchar(255) ILIKE :dId`, { dId: `${q}` })
})
@@ -1,6 +1,6 @@
import _ from "lodash"
import { BaseService } from "medusa-interfaces"
import { Brackets, Raw, IsNull } from "typeorm"
import { Brackets, Raw, IsNull, ILike } from "typeorm"
import { Validator, MedusaError } from "medusa-core-utils"
/**
@@ -558,14 +558,11 @@ class ProductVariantService extends BaseService {
}
query.where = qb => {
qb.where(where).andWhere(
new Brackets(qb => {
qb.where([
{ sku: Raw(a => `${a} ILIKE :q`, { q: `%${q}%` }) },
{ title: Raw(a => `${a} ILIKE :q`, { q: `%${q}%` }) },
]).orWhere(`product.title ILIKE :q`, { q: `%${q}%` })
})
)
qb.where(where).andWhere([
{ sku: ILike(`%${q}%`) },
{ title: ILike(`%${q}%`) },
{ product: { title: ILike(`%${q}%`) } },
])
}
}