how to deal with testing that uses uuid inside the component - vue.js

I try to test my component that has a function to add an item to the array and each of those items has UUID property but I get this error when I try to run the unit test for that.
TypeError: Cannot read property 'v1' of undefined
const basicDataItem = {
> 380 | id: this.$uuid.v1()
How can I test the code that uses UUID like in this case?
edit:
this is the function that I want to test
addDataItem(key) {
const basicDataItem = {
id: this.$uuid.v1(),
units: '',
price: '',
label: '',
};
this.editableData[key].push(basicDataItem);
}

Here is a unit test solution for your case:
index.js:
export class SomeClass {
editableData = {
jest: []
};
$uuid = {
v1() {
return 'real uuid';
}
};
addDataItem(key) {
const basicDataItem = {
id: this.$uuid.v1(),
units: '',
price: '',
label: ''
};
this.editableData[key].push(basicDataItem);
}
}
index.spec.js:
import { SomeClass } from './';
describe('SomeClass', () => {
test('should add data item', () => {
const someClassInstance = new SomeClass();
const uuidv1Spy = jest.spyOn(someClassInstance.$uuid, 'v1').mockReturnValueOnce('fake uuid');
someClassInstance.addDataItem('jest');
expect(uuidv1Spy).toBeCalledTimes(1);
expect(someClassInstance.editableData).toEqual({ jest: [{ id: 'fake uuid', units: '', price: '', label: '' }] });
});
});
Unit test result with coverage report:
PASS src/stackoverflow/58710736/index.spec.js
SomeClass
✓ should add data item (14ms)
----------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files | 88.89 | 100 | 66.67 | 87.5 | |
index.js | 88.89 | 100 | 66.67 | 87.5 | 7 |
----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 3.909s, estimated 6s
Source code: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/58710736

Related

react hook form typescript rules error when using returntype

I want to get the ReturnType of useControllerProps rules but I get an ts error:
Type 'Omit<Partial<{ required: string | ValidationRule<boolean>; min: ValidationRule<string | number>; max: ValidationRule<string | number>; ... 12 more ...; deps: string | string[]; }>, "valueAsNumber" | ... 2 more ... | "disabled"> | undefined' does not satisfy the constraint '(...args: any) => any'.
Type 'undefined' is not assignable to type '(...args: any) => any'.ts(2344)
Code:
export interface IReactHookFormInput {
label: string;
name: string;
rules: ReturnType<UseControllerProps['rules']>
}

Why did the foreign key constraint fail on the column `postId`?

Why did the foreign key constraint fail on the column: postId? How can I fill the prisma studio with the same postId values?
Faker create table git example
Manual filling git example
enter image description here
images: {
create: [
{
imagePuth: faker.image.image(),
postId: faker.datatype.number({ min: 1, max: 7 }),
},
],
},
Environment variables loaded from .env
Running seed command `ts-node prisma/seed.ts` ...
Start seeding ...
PrismaClientKnownRequestError:
Invalid `prisma.user.create()` invocation in
Z:\spa\project\server\prisma\seed.ts:18:36
15 async function main() {
16 console.log(`Start seeding ...`);
17 for (let i = 0; i < 7; i++) {
→ 18 const user = await prisma.user.create(
Foreign key constraint failed on the field: `postId`
at cb (Z:\spa\project\server\node_modules\#prisma\client\runtime\index.js:38537:17)
at async main (Z:\spa\project\server\prisma\seed.ts:18:18) {
code: 'P2003',`enter code here`
clientVersion: '3.3.0',
meta: { field_name: 'postId' }
}
An error occured while running the seed command:
Error: Command failed with exit code 1: ts-node prisma/seed.ts
enter image description here
images: {
create: [
{
imagePuth: faker.image.image(),
postId: 1,
},
],
},
console.log('postId ' + faker.datatype.number({ min: 1, max: 7 }));
console.log(`Created user with id: ${user.id}`);
Running seed command `ts-node prisma/seed.ts` ...
Start seeding ...
postId 7
Created user with id: 1
postId 3`enter code here`
Created user with id: 2
postId 5
Created user with id: 3
postId 7
Created user with id: 4
postId 5
Created user with id: 5
postId 5
Created user with id: 6
postId 7
Created user with id: 7
Seeding finished.
The seed command has been executed.
images: {
create: [
{
imagePuth: faker.image.image(),
postId: 2,
},
],
},
enter image description here
Thank you I did so
Tasin Ishmam
import { PrismaClient, Prisma } from '#prisma/client';
//import faker from 'faker';
const prisma = new PrismaClient();
const faker = require('faker');
async function main() {
console.log(`Start seeding ...`);
for (let i = 0; i < 7; i++) {
const user = await prisma.user.create({
data: {
email: faker.internet.email(),
firstName: faker.name.firstName(),
lastName: faker.name.lastName(),
avatar: faker.image.avatar(),
},
});
console.log({ user });
}
for (let i = 0; i < 7; i++) {
const post = await prisma.post.create({
data: {
title: faker.name.title(),
content: faker.lorem.paragraphs(),
userId: faker.datatype.number({ min: 1, max: 7 }),
},
});
console.log({ post });
}
for (let i = 0; i < 14; i++) {
const image = await prisma.image.create({
data: {
imagePuth: faker.image.image(),
postId: faker.datatype.number({ min: 1, max: 7 }),
userId: faker.datatype.number({ min: 1, max: 7 }),
},
});
console.log({ image });
}
console.log(`Seeding finished.`);
}
main()
.catch((e) => {
console.error(e);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
});

How Test e2e Nestjs API with GRAPHQL

When I create my Owner via graphql-playground it works fine,
but my test fail and response me that 'body.data.createOwner is undefined', there no data.
// owner.e2e.spec.ts
describe('Owner test (e2e)', () => {
let app: INestApplication;
beforeAll(async () => {
const moduleRef = await Test.createTestingModule({
imports: [
GraphQLModule.forRoot({
autoSchemaFile: join(process.cwd(), 'src/schema.gql'),
}),
OwnerModule,
DatabaseModule
]
}).compile();
app = moduleRef.createNestApplication();
await app.init();
});
afterAll(async () => {
await app.close();
})
const createOwnerQuery = `
mutation createOwner($OwnerInput: OwnerInput!) {
createOwner(ownerInput: $OwnerInput) {
_id
name
firstname
email
password
firstsub
expsub
createdAt
updatedAt
}
}
`;
let id: string = '';
it('createOwner', () => {
return request(app.getHttpServer())
.post('/graphql')
.send({
operationName: 'createOwner',
variables: {
OwnerInput: {
name: 'adar',
firstname: 'adar',
email: 'adar#test.com',
password: 'testing',
firstsub: '2020-08-14',
expsub: '2020-07-13'
}
},
query: createOwnerQuery,
})
.expect(({ body }) => {
const data = body.data.createOwner <-- test fail at this line
id = data._id
expect(data.name).toBe(owner.name)
expect(data.email).toBe(owner.email)
expect(data.firstsub).toBe(owner.firstsub)
})
.expect(200)
})
// Output terminal
FAIL test/owner.e2e-spec.ts (9.567 s)
Owner test (e2e)
✕ createOwner (79 ms)
● Owner test (e2e) › createOwner
TypeError: Cannot read property 'createOwner' of undefined
98 | })
99 | .expect(({ body }) => {
> 100 | const data = body.data.createOwner
| ^
101 | id = data._id
102 | expect(data.name).toBe(owner.name)
103 | expect(data.email).toBe(owner.email)
at owner.e2e-spec.ts:100:40
at Test._assertFunction (../node_modules/supertest/lib/test.js:283:11)
at Test.assert (../node_modules/supertest/lib/test.js:173:18)
at Server.localAssert (../node_modules/supertest/lib/test.js:131:12)
Test Suites: 1 failed, 1 total
Tests: 1 failed, 1 total
Snapshots: 0 total
Time: 9.645 s, estimated 10 s
Ran all test suites.
My problem was from CLI plugin which generate automatically nullable Graphql fields without putting the #Field decorator in my ObjectType.
The creator of nest gave a trick about this issue.
--> https://github.com/nestjs/graphql/issues/810
but this doesn't works for me, so I simply added "#Field" decorator to all attributs in my model #ObjectType().

Replacing the query causing NavigationDuplicated error in Vue-router

I need to remove the value from arrayed query parameter. Suppose, when query is
{
item_ids: [ "12", "13" ],
other_param: [ "alpha", "bravo" ]
}
my function removeElementFromArrayedQueryParameter('item_ids', 13) must turn query to:
{
item_ids: [ "12" ],
other_param: [ "alpha", "bravo" ]
}
Implementation (TypeScript):
function removeElementFromArrayedQueryParameter(key: string, value: string): void {
/** 〔Theory〕 Preventing 'NavigationDuplicated: Navigating to current location ("/〇〇") is not allowed' */
if (isEmptyObject(RoutingHelper.router.currentRoute.query)) {
return;
}
if (!Array.isArray(RoutingHelper.router.currentRoute.query[key])) {
return;
}
const updatedQuery: QueryParameters = {
...RoutingHelper.router.currentRoute.query as object
};
removeSingleElementFromArrayByPredicateMutably(
updatedQuery[key] as Array<string>, (arrayElement: string): boolean => arrayElement === value
);
console.log(JSON.stringify(updatedQuery, null, 2)); // I checked: the element has been romoved
// it's the router instance created by new VueRouter({})
RoutingHelper.router.push({
query: updatedQuery
})
.catch((error: Error): void => {
console.error(error)
});
}
function isEmptyObject(potentialObject: unknown): potentialObject is object {
if (typeof potentialObject !== "object" || potentialObject === null) {
return false;
}
return Object.entries(potentialObject as {[key: string]: unknown}).length === 0;
}
Although the removing of target element from updatedQuery successful (checked by manual testing), I have console error:
{
"_name": "NavigationDuplicated",
"name": "NavigationDuplicated",
"message": "Navigating to current location (\"/page?item_ids=12\") is not allowed"
}
"message" in console error contains right target location, but actually one of item_ids has not been removed from URI.
The console error is right about route name is same, but I don't going to redirect on same page: I just want to remove one query parameter. router.push casts similar error.
Update
Please note that TypeScript does not allow to write as
this.$router.replace({
...this.$router.currentRoute,
query
});
TS2769: No overload matches this call.
Overload 1 of 2, '(location: RawLocation): Promise<Route>', gave the following error.
Argument of type '{ query: Dictionary<string | (string | null)[] | null | undefined>; path: string; name?: string |
null | undefined; hash: string; params: Dictionary<string>; fullPath: string; matched: RouteRecord[]; redirectedFrom?: s
tring | undefined; meta?: any; }' is not assignable to parameter of type 'RawLocation'.
Type '{ query: Dictionary<string | (string | null)[] | null | undefined>; path: string; name?: string | null | und
efined; hash: string; params: Dictionary<string>; fullPath: string; matched: RouteRecord[]; redirectedFrom?: string | un
defined; meta?: any; }' is not assignable to type 'Location'.
Types of property 'name' are incompatible.
Type 'string | null | undefined' is not assignable to type 'string | undefined'.
Type 'null' is not assignable to type 'string | undefined'.
Overload 2 of 2, '(location: RawLocation, onComplete?: Function | undefined, onAbort?: ErrorHandler | undefined): void
', gave the following error.
Argument of type '{ query: Dictionary<string | (string | null)[] | null | undefined>; path: string; name?: string |
null | undefined; hash: string; params: Dictionary<string>; fullPath: string; matched: RouteRecord[]; redirectedFrom?: s
tring | undefined; meta?: any; }' is not assignable to parameter of type 'RawLocation'.
Type '{ query: Dictionary<string | (string | null)[] | null | undefined>; path: string; name?: string | null | und
efined; hash: string; params: Dictionary<string>; fullPath: string; matched: RouteRecord[]; redirectedFrom?: string | un
defined; meta?: any; }' is not assignable to type 'Location'.
Types of property 'name' are incompatible.
Type 'string | null | undefined' is not assignable to type 'string | undefined'.
Type 'null' is not assignable to type 'string | undefined'.
If the are no mistake in TypeScript types, above solution is not safe.
this.$router.replace({
...this.$router.name === null ? {} : RoutingHelper.router.currentRoute,
query: updatedQuery
})
does not fix it.
You should update your new route like this
function removeFromQuery(route, queryName, queryValue)
{
const query = Object.assign({}, route.query);
if (queryName in query)
{
const idx = query[queryName].indexOf(queryValue);
if (idx !== -1)
{
query[queryName].splice(idx, 1);
this.$router.replace({
...this.$router.currentRoute,
query
});
}
}
}
The updatedQuery query is not the deep clone of RoutingHelper.router.currentRoute.query. Below code is not enough to create the deep copy of query:
const updatedQuery: QueryParameters = {
...RoutingHelper.router.currentRoute.query as object
};
So, when execute
RoutingHelper.router.push({
query: updatedQuery
})
we don't subtitute query to new value. That why error occurs.
Use lodash or other libraries provides deep cloning, or use own implementation of deep cloning.

How to mock a class being imported from a npm module

I am importing a class via const { PaymentRequest } = require("react-native-payments"); and I am trying to mock the functions it exposes when it is instantiated. For example:
const paymentRequest = new PaymentRequest(METHOD_DATA, DETAILS, OPTIONS);
paymentRequest.canMakePayments().then(res => {...})
I want to mock this and change the value coming back from the promise resolve so that I can test different scenarios from canMakePayments and other async functions the class exposes.
Here is the solution, you can use jest.mock method mock react-native-payments module manually.
index.ts:
const { PaymentRequest } = require('react-native-payments');
const METHOD_DATA = [
{
supportedMethods: ['apple-pay'],
data: {
merchantIdentifier: 'merchant.com.your-app.namespace',
supportedNetworks: ['visa', 'mastercard', 'amex'],
countryCode: 'US',
currencyCode: 'USD'
}
}
];
const DETAILS = {
id: 'basic-example',
displayItems: [
{
label: 'Movie Ticket',
amount: { currency: 'USD', value: '15.00' }
}
],
total: {
label: 'Merchant Name',
amount: { currency: 'USD', value: '15.00' }
}
};
const OPTIONS = {
requestPayerName: true
};
function main() {
const paymentRequest = new PaymentRequest(METHOD_DATA, DETAILS, OPTIONS);
return paymentRequest.canMakePayment();
}
export { main, METHOD_DATA, DETAILS, OPTIONS };
main function is going to be tested.
index.spec.ts:
import { main, METHOD_DATA, DETAILS, OPTIONS } from './';
const { PaymentRequest } = require('react-native-payments');
jest.mock('react-native-payments', () => {
const PaymentRequestMocked = {
canMakePayment: jest.fn()
};
return {
PaymentRequest: jest.fn(() => PaymentRequestMocked)
};
});
const paymentRequest = new PaymentRequest(METHOD_DATA, DETAILS, OPTIONS);
describe('main', () => {
beforeEach(() => {
paymentRequest.canMakePayment.mockReset();
});
it.each`
value | name
${'mocked value 1'} | ${'t1'}
${'mocked value 2'} | ${'t2'}
`(`$name`, async ({ value }) => {
paymentRequest.canMakePayment.mockResolvedValueOnce(value);
const actualValue = await main();
expect(actualValue).toEqual(value);
expect(paymentRequest.canMakePayment).toBeCalledTimes(1);
});
});
Unit test result with 100% coverage:
PASS src/stackoverflow/57565053/index.spec.ts
main
✓ t1 (5ms)
✓ t2 (1ms)
----------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files | 100 | 100 | 100 | 100 | |
index.ts | 100 | 100 | 100 | 100 | |
----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 3.03s, estimated 6s
Here is the completed demo: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/57565053