Skip to content

Commit

Permalink
feature: add cart functionality into Customer service #40
Browse files Browse the repository at this point in the history
Add cart functionality into database in the Customer service, and update UI functionality according.
The cart services will store the customers' cart into database.
Previously the cart is only kept on React's state, which does not persists after hard reloading.

Close #39
  • Loading branch information
ckng0221 authored Feb 2, 2024
2 parents 5cd1741 + 3b57106 commit c71309f
Show file tree
Hide file tree
Showing 16 changed files with 625 additions and 148 deletions.
318 changes: 226 additions & 92 deletions apps/customer/src/customer.controller.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,33 @@ import { getModelToken } from '@nestjs/mongoose';
import { Test, TestingModule } from '@nestjs/testing';
import { MongoMemoryServer } from 'mongodb-memory-server';
import { Connection, Model, Types, connect } from 'mongoose';
import { CustomerController } from './customer.controller';
import { CustomerCredentialService, CustomerService } from './customer.service';
import { CustomerDtoStub } from './dto/customer.dto.stub';
import {
CustomerCartController,
CustomerController,
} from './customer.controller';
import {
CustomerCartService,
CustomerCredentialService,
CustomerService,
} from './customer.service';
import { CustomerCartDtoStub, CustomerDtoStub } from './dto/customer.dto.stub';
import {
Customer,
CustomerCart,
CustomerCartSchema,
CustomerCredential,
CustomerCredentialSchema,
CustomerSchema,
} from './schemas/customer.schema';

describe('customerController', () => {
let customerController: CustomerController;
let customerCartController: CustomerCartController;
let mongod: MongoMemoryServer;
let mongoConnection: Connection;
let customerModel: Model<Customer>;
let customerCredentialModel: Model<CustomerCredential>;
let customerCartModel: Model<CustomerCart>;

beforeAll(async () => {
mongod = await MongoMemoryServer.create();
Expand All @@ -28,19 +39,31 @@ describe('customerController', () => {
CustomerCredential.name,
CustomerCredentialSchema,
);
customerCartModel = mongoConnection.model(
CustomerCart.name,
CustomerCartSchema,
);
const app: TestingModule = await Test.createTestingModule({
controllers: [CustomerController],
controllers: [CustomerController, CustomerCartController],
providers: [
CustomerService,
CustomerCredentialService,
CustomerCartService,
{ provide: getModelToken(Customer.name), useValue: customerModel },
{
provide: getModelToken(CustomerCredential.name),
useValue: customerCredentialModel,
},
{
provide: getModelToken(CustomerCart.name),
useValue: customerCartModel,
},
],
}).compile();
customerController = app.get<CustomerController>(CustomerController);
customerCartController = app.get<CustomerCartController>(
CustomerCartController,
);
});

afterAll(async () => {
Expand All @@ -57,110 +80,221 @@ describe('customerController', () => {
}
});

describe('Create customer', () => {
it('should return the saved object', async () => {
const createdCustomer =
await customerController.create(CustomerDtoStub());
expect(createdCustomer.name).toBe(CustomerDtoStub().name);
describe('Customer Controller', () => {
describe('Create customer', () => {
it('should return the saved object', async () => {
const createdCustomer =
await customerController.create(CustomerDtoStub());
expect(createdCustomer.name).toBe(CustomerDtoStub().name);
});
});
});

describe('Find all', () => {
it('should return all the saved objects', async () => {
const customer1 = await new customerModel(
CustomerDtoStub({ name: 'Name1' }),
).save();
const customer2 = await new customerModel(
CustomerDtoStub({ name: 'Name2' }),
).save();
const customers = await customerController.findAll();
expect(customers).toEqual(
expect.arrayContaining([
expect.objectContaining(customer1.toObject()),
expect.objectContaining(customer2.toObject()),
]),
);
describe('Find all', () => {
it('should return all the saved objects', async () => {
const customer1 = await new customerModel(
CustomerDtoStub({ name: 'Name1' }),
).save();
const customer2 = await new customerModel(
CustomerDtoStub({ name: 'Name2' }),
).save();
const customers = await customerController.findAll();
expect(customers).toEqual(
expect.arrayContaining([
expect.objectContaining(customer1.toObject()),
expect.objectContaining(customer2.toObject()),
]),
);
});
it('should return null', async () => {
const id = new Types.ObjectId().toString();
const customer = await customerController.findOne(id);
expect(customer).toBeNull();
});
describe('Search function', () => {
let customer1: Partial<Customer>;
let customer2: Partial<Customer>;
beforeEach(async () => {
customer1 = {
name: 'Ng',
email: 'ngtesting@google.com',
};
customer2 = {
name: 'CK',
email: 'ckmocking@aws.com',
};

await new customerModel(CustomerDtoStub(customer1)).save();
await new customerModel(CustomerDtoStub(customer2)).save();
});
it('can search by name', async () => {
const customerObjs = await customerController.findAll({
search: 'ng',
});
const customers = customerObjs.map((customer) => customer.name);
expect(customers).toContain(customer1.name);
expect(customers.length).toBe(1);
});
it('can search by email', async () => {
const customerObjs = await customerController.findAll({
search: 'ngtesting@google.com',
});

const customers = customerObjs.map((customer) => customer.email);
expect(customers).toContain(customer1.email);
// expect(customers.length).toBe(1); # NOTE: Difficulte to get exact match when use search string
});
});
});
it('should return null', async () => {
const id = new Types.ObjectId().toString();
const customer = await customerController.findOne(id);
expect(customer).toBeNull();

describe('Find one', () => {
it('should return the corresponding saved object', async () => {
const customer = await new customerModel(CustomerDtoStub()).save();
const foundCustomer = await customerController.findOne(
customer._id.toString(),
);
expect(foundCustomer.name).toBe(customer.name);
});
it('should return null', async () => {
const id = new Types.ObjectId().toString();
const customer = await customerController.findOne(id);
expect(customer).toBeNull();
});
});
describe('Search function', () => {
let customer1: Partial<Customer>;
let customer2: Partial<Customer>;
beforeEach(async () => {
customer1 = {
name: 'Ng',
email: 'ngtesting@google.com',
};
customer2 = {
name: 'CK',
email: 'ckmocking@aws.com',
};

await new customerModel(CustomerDtoStub(customer1)).save();
await new customerModel(CustomerDtoStub(customer2)).save();

describe('Update one', () => {
it('should return the corresponding updated object', async () => {
const updatedName = 'Titlte1-updated';
const customer = await new customerModel(
CustomerDtoStub({ name: 'Name1' }),
).save();
const updatedCustomer = await customerController.updateOne(
customer._id.toString(),
{
name: updatedName,
},
);
expect(updatedCustomer.name).toBe(updatedName);
});
it('can search by name', async () => {
const customerObjs = await customerController.findAll({
search: 'ng',
});
const customers = customerObjs.map((customer) => customer.name);
expect(customers).toContain(customer1.name);
expect(customers.length).toBe(1);
});

describe('Delete one', () => {
it('should return null', async () => {
const customer = await new customerModel(CustomerDtoStub()).save();
await customerController.deleteOne(customer._id.toString());
const foundCustomer = await customerController.findOne(
customer._id.toString(),
);
expect(foundCustomer).toBeNull();
});
it('can search by email', async () => {
const customerObjs = await customerController.findAll({
search: 'ngtesting@google.com',
});
});

const customers = customerObjs.map((customer) => customer.email);
expect(customers).toContain(customer1.email);
// expect(customers.length).toBe(1); # NOTE: Difficulte to get exact match when use search string
describe('Find all carts by customer', () => {
it('should return empty', async () => {
const customer = await new customerModel(CustomerDtoStub()).save();

const carts = await customerController.findOneCarts(
customer._id.toString(),
);

expect(carts.length).toBe(0);
});

it('should return carts based on customer', async () => {
const customer = await new customerModel(CustomerDtoStub()).save();
const carts = await new customerCartModel(
CustomerCartDtoStub({ customer: customer._id.toString() as any }),

Check warning on line 205 in apps/customer/src/customer.controller.spec.ts

View workflow job for this annotation

GitHub Actions / build (20.x)

Unexpected any. Specify a different type

Check warning on line 205 in apps/customer/src/customer.controller.spec.ts

View workflow job for this annotation

GitHub Actions / build (20.x)

Unexpected any. Specify a different type
).save();

console.log(carts);
console.log(customer._id.toString());

const foundCarts = await customerController.findOneCarts(
customer?._id.toString(),
);

expect(foundCarts.length).toBe(1);
});
});
});

describe('Find one', () => {
it('should return the corresponding saved object', async () => {
const customer = await new customerModel(CustomerDtoStub()).save();
const foundCustomer = await customerController.findOne(
customer._id.toString(),
);
expect(foundCustomer.name).toBe(customer.name);
describe('Customer Cart Controller', () => {
describe('Create customer Cart', () => {
it('should return the saved object', async () => {
const customer_id = new Types.ObjectId();
const book_id = new Types.ObjectId();

const customerCart: any = CustomerCartDtoStub({

Check warning on line 226 in apps/customer/src/customer.controller.spec.ts

View workflow job for this annotation

GitHub Actions / build (20.x)

Unexpected any. Specify a different type

Check warning on line 226 in apps/customer/src/customer.controller.spec.ts

View workflow job for this annotation

GitHub Actions / build (20.x)

Unexpected any. Specify a different type
customer: customer_id,
book_id,
});

const createdCustomerCart = await customerCartController.create(
customerCart,
{
user: { sub: customer_id },
} as any,

Check warning on line 235 in apps/customer/src/customer.controller.spec.ts

View workflow job for this annotation

GitHub Actions / build (20.x)

Unexpected any. Specify a different type

Check warning on line 235 in apps/customer/src/customer.controller.spec.ts

View workflow job for this annotation

GitHub Actions / build (20.x)

Unexpected any. Specify a different type
);
expect(createdCustomerCart._id.toString()).toBe(
customerCart._id.toString(),
);
});
});
it('should return null', async () => {
const id = new Types.ObjectId().toString();
const customer = await customerController.findOne(id);
expect(customer).toBeNull();

describe('Find one', () => {
it('should return the corresponding saved object', async () => {
const customer_id = new Types.ObjectId();
const book_id = new Types.ObjectId();

const customerCart = await new customerCartModel(
CustomerCartDtoStub({ customer: customer_id, book_id }),
).save();
const foundCustomerCart = await customerCartController.findOne(
customerCart._id.toString(),
);
expect(foundCustomerCart._id.toString()).toBe(
customerCart._id.toString(),
);
});
it('should return null', async () => {
const id = new Types.ObjectId().toString();
const customerCart = await customerCartController.findOne(id);
expect(customerCart).toBeNull();
});
});
});

describe('Update one', () => {
it('should return the corresponding updated object', async () => {
const updatedName = 'Titlte1-updated';
const customer = await new customerModel(
CustomerDtoStub({ name: 'Name1' }),
).save();
const updatedCustomer = await customerController.updateOne(
customer._id.toString(),
{
name: updatedName,
},
);
expect(updatedCustomer.name).toBe(updatedName);
describe('Update one', () => {
it('should return the corresponding updated object', async () => {
const updatedQuantity = 2;
const customerCart = await new customerCartModel(
CustomerCartDtoStub({ quantity: 1 }),
).save();
const updatedCustomer = await customerCartController.updateOne(
customerCart._id.toString(),
{
quantity: 2,
},
);
expect(updatedCustomer.quantity).toBe(updatedQuantity);
});
});
});

describe('Delete one', () => {
it('should return null', async () => {
const customer = await new customerModel(CustomerDtoStub()).save();
await customerController.deleteOne(customer._id.toString());
const foundCustomer = await customerController.findOne(
customer._id.toString(),
);
expect(foundCustomer).toBeNull();
describe('Delete one', () => {
it('should return null', async () => {
const customer_id = new Types.ObjectId();

const customerCart = await new customerCartModel(
CustomerCartDtoStub({ customer: customer_id.toString() as any }),

Check warning on line 286 in apps/customer/src/customer.controller.spec.ts

View workflow job for this annotation

GitHub Actions / build (20.x)

Unexpected any. Specify a different type

Check warning on line 286 in apps/customer/src/customer.controller.spec.ts

View workflow job for this annotation

GitHub Actions / build (20.x)

Unexpected any. Specify a different type
).save();

await customerCartController.deleteOne(customerCart._id.toString(), {
user: { sub: customer_id.toString() },
} as any);

Check warning on line 291 in apps/customer/src/customer.controller.spec.ts

View workflow job for this annotation

GitHub Actions / build (20.x)

Unexpected any. Specify a different type

Check warning on line 291 in apps/customer/src/customer.controller.spec.ts

View workflow job for this annotation

GitHub Actions / build (20.x)

Unexpected any. Specify a different type
const foundCustomerCart = await customerCartController.findOne(
customerCart._id.toString(),
);

expect(foundCustomerCart).toBeNull();
});
});
});
});
Loading

0 comments on commit c71309f

Please sign in to comment.