Skip to content

Commit 2769533

Browse files
committed
chore: add more tests
Signed-off-by: dhmlau <dhmlau@ca.ibm.com>
1 parent b559064 commit 2769533

File tree

20 files changed

+3620
-1
lines changed

20 files changed

+3620
-1
lines changed
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
// Copyright IBM Corp. and LoopBack contributors 2018,2026. All Rights Reserved.
2+
// Node module: @loopback/example-soap-calculator
3+
// This file is licensed under the MIT License.
4+
// License text available at https://opensource.org/licenses/MIT
5+
6+
import {expect} from '@loopback/testlab';
7+
import {CalculatorController} from '../../../controllers/calculator.controller';
8+
import {
9+
AddResponse,
10+
CalculatorParameters,
11+
CalculatorService,
12+
DivideResponse,
13+
MultiplyResponse,
14+
SubtractResponse,
15+
} from '../../../services/calculator.service';
16+
17+
describe('CalculatorController (unit)', () => {
18+
let controller: CalculatorController;
19+
let calculatorService: CalculatorService;
20+
21+
beforeEach(givenController);
22+
23+
describe('multiply', () => {
24+
it('calls the service with correct parameters', async () => {
25+
const result = await controller.multiply(5, 3);
26+
expect(result).to.deepEqual({result: {value: 15}});
27+
});
28+
29+
it('handles zero multiplication', async () => {
30+
const result = await controller.multiply(0, 10);
31+
expect(result).to.deepEqual({result: {value: 0}});
32+
});
33+
34+
it('handles negative numbers', async () => {
35+
const result = await controller.multiply(-5, 3);
36+
expect(result).to.deepEqual({result: {value: -15}});
37+
});
38+
39+
it('handles large numbers', async () => {
40+
const result = await controller.multiply(1000, 1000);
41+
expect(result).to.deepEqual({result: {value: 1000000}});
42+
});
43+
});
44+
45+
describe('add', () => {
46+
it('calls the service with correct parameters', async () => {
47+
const result = await controller.add(10, 5);
48+
expect(result).to.deepEqual({result: {value: 15}});
49+
});
50+
51+
it('handles zero addition', async () => {
52+
const result = await controller.add(0, 0);
53+
expect(result).to.deepEqual({result: {value: 0}});
54+
});
55+
56+
it('handles negative numbers', async () => {
57+
const result = await controller.add(-5, 3);
58+
expect(result).to.deepEqual({result: {value: -2}});
59+
});
60+
61+
it('handles large numbers', async () => {
62+
const result = await controller.add(999999, 1);
63+
expect(result).to.deepEqual({result: {value: 1000000}});
64+
});
65+
});
66+
67+
describe('subtract', () => {
68+
it('calls the service with correct parameters', async () => {
69+
const result = await controller.subtract(10, 5);
70+
expect(result).to.deepEqual({result: {value: 5}});
71+
});
72+
73+
it('handles zero subtraction', async () => {
74+
const result = await controller.subtract(10, 0);
75+
expect(result).to.deepEqual({result: {value: 10}});
76+
});
77+
78+
it('handles negative results', async () => {
79+
const result = await controller.subtract(5, 10);
80+
expect(result).to.deepEqual({result: {value: -5}});
81+
});
82+
83+
it('handles negative numbers', async () => {
84+
const result = await controller.subtract(-5, -3);
85+
expect(result).to.deepEqual({result: {value: -2}});
86+
});
87+
});
88+
89+
describe('divide', () => {
90+
it('calls the service with correct parameters', async () => {
91+
const result = await controller.divide(10, 2);
92+
expect(result).to.deepEqual({result: {value: 5}});
93+
});
94+
95+
it('throws error when dividing by zero', async () => {
96+
await expect(controller.divide(10, 0)).to.be.rejectedWith(
97+
/Cannot divide by zero/,
98+
);
99+
});
100+
101+
it('handles division resulting in decimal', async () => {
102+
const result = await controller.divide(10, 3);
103+
expect(result.result.value).to.be.approximately(3.33, 0.01);
104+
});
105+
106+
it('handles negative numbers', async () => {
107+
const result = await controller.divide(-10, 2);
108+
expect(result).to.deepEqual({result: {value: -5}});
109+
});
110+
111+
it('handles division by one', async () => {
112+
const result = await controller.divide(42, 1);
113+
expect(result).to.deepEqual({result: {value: 42}});
114+
});
115+
116+
it('handles division of zero', async () => {
117+
const result = await controller.divide(0, 5);
118+
expect(result).to.deepEqual({result: {value: 0}});
119+
});
120+
});
121+
122+
describe('edge cases', () => {
123+
it('multiply handles very small numbers', async () => {
124+
const result = await controller.multiply(1, 1);
125+
expect(result).to.deepEqual({result: {value: 1}});
126+
});
127+
128+
it('add handles same numbers', async () => {
129+
const result = await controller.add(7, 7);
130+
expect(result).to.deepEqual({result: {value: 14}});
131+
});
132+
133+
it('subtract results in zero', async () => {
134+
const result = await controller.subtract(5, 5);
135+
expect(result).to.deepEqual({result: {value: 0}});
136+
});
137+
138+
it('divide handles equal numbers', async () => {
139+
const result = await controller.divide(8, 8);
140+
expect(result).to.deepEqual({result: {value: 1}});
141+
});
142+
});
143+
144+
function givenController() {
145+
calculatorService = givenCalculatorService();
146+
controller = new CalculatorController(calculatorService);
147+
}
148+
149+
function givenCalculatorService(): CalculatorService {
150+
return {
151+
async multiply(args: CalculatorParameters): Promise<MultiplyResponse> {
152+
return {result: {value: args.intA * args.intB}};
153+
},
154+
async add(args: CalculatorParameters): Promise<AddResponse> {
155+
return {result: {value: args.intA + args.intB}};
156+
},
157+
async subtract(args: CalculatorParameters): Promise<SubtractResponse> {
158+
return {result: {value: args.intA - args.intB}};
159+
},
160+
async divide(args: CalculatorParameters): Promise<DivideResponse> {
161+
return {result: {value: args.intA / args.intB}};
162+
},
163+
};
164+
}
165+
});
166+
167+
// Made with Bob
Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
// Copyright IBM Corp. and LoopBack contributors 2018,2026. All Rights Reserved.
2+
// Node module: @loopback/example-todo
3+
// This file is licensed under the MIT License.
4+
// License text available at https://opensource.org/licenses/MIT
5+
6+
import {expect} from '@loopback/testlab';
7+
import {Todo} from '../../../models';
8+
9+
describe('Todo (unit)', () => {
10+
describe('constructor', () => {
11+
it('creates an instance with no data', () => {
12+
const todo = new Todo();
13+
expect(todo).to.be.instanceOf(Todo);
14+
});
15+
16+
it('creates an instance with partial data', () => {
17+
const todo = new Todo({
18+
title: 'Test Todo',
19+
});
20+
expect(todo.title).to.equal('Test Todo');
21+
expect(todo.id).to.be.undefined();
22+
expect(todo.desc).to.be.undefined();
23+
});
24+
25+
it('creates an instance with complete data', () => {
26+
const data = {
27+
id: 1,
28+
title: 'Test Todo',
29+
desc: 'Test Description',
30+
isComplete: false,
31+
remindAtAddress: '123 Main St, City, 12345',
32+
remindAtGeo: '40.7128,-74.0060',
33+
tag: {priority: 'high'},
34+
};
35+
const todo = new Todo(data);
36+
expect(todo.id).to.equal(1);
37+
expect(todo.title).to.equal('Test Todo');
38+
expect(todo.desc).to.equal('Test Description');
39+
expect(todo.isComplete).to.be.false();
40+
expect(todo.remindAtAddress).to.equal('123 Main St, City, 12345');
41+
expect(todo.remindAtGeo).to.equal('40.7128,-74.0060');
42+
expect(todo.tag).to.deepEqual({priority: 'high'});
43+
});
44+
});
45+
46+
describe('properties', () => {
47+
it('has optional id property', () => {
48+
const todo = new Todo({title: 'Test'});
49+
expect(todo).to.not.have.property('id');
50+
51+
todo.id = 1;
52+
expect(todo.id).to.equal(1);
53+
});
54+
55+
it('has required title property', () => {
56+
const todo = new Todo({title: 'Required Title'});
57+
expect(todo.title).to.equal('Required Title');
58+
});
59+
60+
it('has optional desc property', () => {
61+
const todo = new Todo({title: 'Test'});
62+
expect(todo.desc).to.be.undefined();
63+
64+
todo.desc = 'Description';
65+
expect(todo.desc).to.equal('Description');
66+
});
67+
68+
it('has optional isComplete property', () => {
69+
const todo = new Todo({title: 'Test'});
70+
expect(todo.isComplete).to.be.undefined();
71+
72+
todo.isComplete = true;
73+
expect(todo.isComplete).to.be.true();
74+
});
75+
76+
it('has optional remindAtAddress property', () => {
77+
const todo = new Todo({title: 'Test'});
78+
expect(todo.remindAtAddress).to.be.undefined();
79+
80+
todo.remindAtAddress = '123 Main St';
81+
expect(todo.remindAtAddress).to.equal('123 Main St');
82+
});
83+
84+
it('has optional remindAtGeo property', () => {
85+
const todo = new Todo({title: 'Test'});
86+
expect(todo.remindAtGeo).to.be.undefined();
87+
88+
todo.remindAtGeo = '40.7128,-74.0060';
89+
expect(todo.remindAtGeo).to.equal('40.7128,-74.0060');
90+
});
91+
92+
it('has optional tag property of any type', () => {
93+
const todo = new Todo({title: 'Test'});
94+
expect(todo.tag).to.be.undefined();
95+
96+
todo.tag = {priority: 'high', category: 'work'};
97+
expect(todo.tag).to.deepEqual({priority: 'high', category: 'work'});
98+
99+
todo.tag = 'simple-tag';
100+
expect(todo.tag).to.equal('simple-tag');
101+
102+
todo.tag = ['tag1', 'tag2'];
103+
expect(todo.tag).to.deepEqual(['tag1', 'tag2']);
104+
});
105+
});
106+
107+
describe('data validation', () => {
108+
it('allows empty description', () => {
109+
const todo = new Todo({
110+
title: 'Test',
111+
desc: '',
112+
});
113+
expect(todo.desc).to.equal('');
114+
});
115+
116+
it('allows false for isComplete', () => {
117+
const todo = new Todo({
118+
title: 'Test',
119+
isComplete: false,
120+
});
121+
expect(todo.isComplete).to.be.false();
122+
});
123+
124+
it('allows true for isComplete', () => {
125+
const todo = new Todo({
126+
title: 'Test',
127+
isComplete: true,
128+
});
129+
expect(todo.isComplete).to.be.true();
130+
});
131+
132+
it('handles complex tag objects', () => {
133+
const complexTag = {
134+
priority: 'high',
135+
labels: ['urgent', 'important'],
136+
metadata: {
137+
createdBy: 'user1',
138+
assignedTo: ['user2', 'user3'],
139+
},
140+
};
141+
const todo = new Todo({
142+
title: 'Test',
143+
tag: complexTag,
144+
});
145+
expect(todo.tag).to.deepEqual(complexTag);
146+
});
147+
});
148+
149+
describe('edge cases', () => {
150+
it('handles very long titles', () => {
151+
const longTitle = 'A'.repeat(1000);
152+
const todo = new Todo({title: longTitle});
153+
expect(todo.title).to.equal(longTitle);
154+
expect(todo.title.length).to.equal(1000);
155+
});
156+
157+
it('handles very long descriptions', () => {
158+
const longDesc = 'B'.repeat(5000);
159+
const todo = new Todo({
160+
title: 'Test',
161+
desc: longDesc,
162+
});
163+
expect(todo.desc).to.equal(longDesc);
164+
expect(todo.desc!.length).to.equal(5000);
165+
});
166+
167+
it('handles special characters in title', () => {
168+
const specialTitle = 'Test @#$%^&*() 测试 🎉';
169+
const todo = new Todo({title: specialTitle});
170+
expect(todo.title).to.equal(specialTitle);
171+
});
172+
173+
it('handles multiline descriptions', () => {
174+
const multilineDesc = 'Line 1\nLine 2\nLine 3';
175+
const todo = new Todo({
176+
title: 'Test',
177+
desc: multilineDesc,
178+
});
179+
expect(todo.desc).to.equal(multilineDesc);
180+
});
181+
182+
it('handles null-like values gracefully', () => {
183+
const todo = new Todo({
184+
title: 'Test',
185+
desc: undefined,
186+
isComplete: undefined,
187+
});
188+
expect(todo.desc).to.be.undefined();
189+
expect(todo.isComplete).to.be.undefined();
190+
});
191+
});
192+
193+
describe('model inheritance', () => {
194+
it('extends Entity class', () => {
195+
const todo = new Todo({title: 'Test'});
196+
expect(todo).to.have.property('toJSON');
197+
expect(todo).to.have.property('toObject');
198+
});
199+
200+
it('can be serialized to JSON', () => {
201+
const todo = new Todo({
202+
id: 1,
203+
title: 'Test Todo',
204+
desc: 'Description',
205+
isComplete: false,
206+
});
207+
const json = todo.toJSON();
208+
expect(json).to.have.property('id', 1);
209+
expect(json).to.have.property('title', 'Test Todo');
210+
expect(json).to.have.property('desc', 'Description');
211+
expect(json).to.have.property('isComplete', false);
212+
});
213+
});
214+
});
215+
216+
// Made with Bob

0 commit comments

Comments
 (0)