I created new project in VueJS with TypeScript.
My component with methods to test:
<template>
<div></div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
#Component
export default class Slider extends Vue {
private slide: number = 0;
private sliding: boolean = false;
public setSlide(slide: number): void {
this.slide = slide;
}
public setSliding(sliding: boolean): void {
this.sliding = sliding;
}
private onSliderStart(slide: any): void {
this.setSliding(true);
}
private onSlideEnd(slide: any): void {
this.setSliding(false);
}
}
</script>
Test:
import { shallowMount } from '#vue/test-utils';
import Slider from '#/components/Header.vue';
describe('Slider', () => {
const wrapper = shallowMount(Slider);
it('check Slider is a Vue Instance', () => {
expect(wrapper.isVueInstance()).toBeTruthy();
});
it('setSlide is func', () => {
expect(typeof wrapper.vm.setSlide).toBe('function')
})
});
and now I would like do test but methods setSlide, setSliding isn't available in wrapper :(
Try this:
import YourComponentHere from "#/components/YourComponentHere";
import { shallowMount, Wrapper } from "#vue/test-utils";
describe("test", () => {
const wrapper: Wrapper<YourComponentHere & { [key: string]: any }>;
it("does something", () => {
expect(wrapper.vm.someThingWhatever).toBe(true);
});
});
The advantage here is that you don't need to cast wrapper.vm to any everytime you use wrapper.vm
It seems you have to cast wrapper.vm as any for TypeScript not to complain:
it('setSlide is func', () => {
expect(typeof (wrapper.vm as any).setSlide).toBe('function')
})
Or at the top of your tests:
const wrapper: any = shallowMount(Slider);
Source: https://github.com/vuejs/vue-test-utils/issues/255#issuecomment-433312728.
Related
Building state with ngxs in angular
//Component.ts
ngOnInit(): void {
const dataInsdeStore = this.store.selectSnapshot(MarketState);
if(!dataInsdeStore.loaded){
const category = this.marketplaceService.getMarketplaceCategories().subscribe(cat => {
const item = this.marketplaceService.getMarketplaceItems().subscribe(i => {
const obj = {
categories: cat,
items: i,
loaded: true
}
this.store.dispatch(new SetMarketAction(obj))
})
})
}
const test = this.store.selectSnapshot(MarketState);
this.store.dispatch(new GetMarketStateAction())
}
Upon checking wether the state is empty or not, and dispatching SetMarketAction I get empty object anyways
//Market.actions.ts
import { MarketStateInterface } from "../interfaces/interfaces";
class SetMarketAction {
static readonly type = '[MARKET] Set';
constructor(public marketState : MarketStateInterface){}
}
class GetMarketStateAction {
static readonly type = '[MARKET] Get';
}
export { SetMarketAction, GetMarketStateAction };
//Market.state.ts
import { Action, State, StateContext } from '#ngxs/store';
import { MarketStateInterface } from '../interfaces/interfaces';
import { Injectable } from '#angular/core';
import { GetMarketStateAction, SetMarketAction } from './market.actions';
#State<MarketStateInterface>({
name: 'market',
defaults: {
categories: [],
items: [],
loaded: false,
},
})
#Injectable()
export class MarketState {
constructor() {}
#Action(GetMarketStateAction)
getMarket(ctx: StateContext<MarketStateInterface>) {
const state = ctx.getState();
console.log(state);
return state;
}
#Action(SetMarketAction)
setMarket(ctx: StateContext<MarketStateInterface>, action: SetMarketAction) {
ctx.setState(action.marketState);
}
}
Every time I conosle.log the state at any given time I get the empty array, the interface of the state is correct
I am calling repository methods inside of the service and now I have to write the unit test for the service. I want to moke repositery Class or Method both.
Here is the service code for which I have to write a test.
import { AttackMatrixRepo } from '../repositories/index';
export const serGetAttackMatrixDetail = async () => {
const attMatRepo = new AttackMatrixRepo();
const table = await attMatRepo.repGetMatric();
return table;
};
Here is the repository code
import { AttackMatrix } from '../entities/index'; // typeorm AttackMatrix schema
import { Repository, BaseEntity } from 'typeorm';
import { AppDataSource } from '../bootstrap/typeorm'; // typeorm connection
export class AttackMatrixRepo extends BaseEntity {
private attackMatrixEntity: Repository<AttackMatrix>;
constructor() {
super();
this.attackMatrixEntity = AppDataSource.getRepository(AttackMatrix);
}
public async repGetMatric() {
return this.attackMatrixEntity.createQueryBuilder('attMatric').getOne();
}
public async getMatrixByStixId({ columNames = ['*'], stixId }): Promise<AttackMatrix> {
const tacticQueryBuilder = await this.attackMatrixEntity.createQueryBuilder('matrix');
const query = tacticQueryBuilder.select(columNames).where('matrix.stix_id = :stixId', { stixId });
return query.getRawOne();
}
}
I am using mobx and decimal.js.
This is my store:
import Decimal from "decimal.js";
import { makeObservable, observable, action } from "mobx";
class MyStore {
public value: Decimal | null = null;
constructor() {
makeObservable(this, {
value: observable,
setValue: action,
});
}
public setValue() {
this.value = new Decimal(100);
}
}
export { MyStore };
This is my component:
import { useStoreValue } from "../../state/StoreContext";
import { observer } from "mobx-react-lite";
const MyPage = observer(() => {
const value = useStoreValue((rootStore) => rootStore.myStore.value);
return <span>{value.mul(5)}</span>;
});
export { MyPage };
As a result I get the following exception:
useObserver.ts:119 Uncaught TypeError: _value.mul is not a function
Any idea what I am missing?
A quick note and edit, it looks like this tutorial might be a winner
https://recursive.codes/blog/post/37
I am using the twilio conversation javascript client sdk on a angular 8 project.
Subscriptions, and async operations are still something I am working on understanding. My entire component that I am using twilio conversations on is below. After i will list my problems.
import {Component, Input, OnInit} from '#angular/core';
import {Client as ConversationsClient} from '#twilio/conversations';
#Component({
selector: 'app-shochat-contentcreator-chat',
templateUrl: './shochat-contentcreator-chat.component.html',
styleUrls: ['./shochat-contentcreator-chat.component.scss']
})
export class ShochatContentcreatorChatComponent implements OnInit {
constructor() { }
#Input() twiliochattoken = null;
conversationsclient;
currentconnectionstate = null;
ngOnInit(): void {
console.log('here we are and stuff tho');
let initConversations = async () => {
this.conversationsclient = await ConversationsClient.create(this.twiliochattoken);
this.conversationsclient.join().then((result) => {
console.log('here is the result of joining the conversation');
console.log(result);
});
}
this.conversationsclient.on("connectionStateChanged", (state) => {
if (state == "connecting") {
this.currentconnectionstate = 'connecting';
}
if (state == "connected") {
this.currentconnectionstate = 'connected';
}
if (state == 'disconnecting') {
this.currentconnectionstate = 'disconnecting';
}
if (state == 'disconnected') {
this.currentconnectionstate = 'disconnected';
}
if (state == 'denied') {
this.currentconnectionstate = 'denied';
}
});
this.conversationsclient.on("conversationJoined", (conversation) => {
console.log('here is the result of the conversationJoined hook');
console.log(conversation);
});
}
}
The below code snippet from the above is the problem:
this.conversationsclient.on("connectionStateChanged", (state) => {
if (state == "connecting") {
this.currentconnectionstate = 'connecting';
}
......
I am getting the error that the code cannot perform the .on function on undefined. Which makes sense, the above function is being called on the init function.
conversationsclient is undefined still. However what is the proper way to put this code? Inside the await ConversationsClient.create(.....) code?
Will that create the subscription that I want for when state changes?
Also how is my code looking based on its intent. I feel like I have missed the mark and not sure if I am close or far from hitting it.
im referencing the following docs
https://www.twilio.com/docs/chat/initializing-sdk-clients
This tutorial has the answer. I need to use a service.
chatservice:
import {EventEmitter, Injectable} from '#angular/core';
import * as Twilio from 'twilio-chat';
import Client from "twilio-chat";
import {Util} from "../util/util";
import {Channel} from "twilio-chat/lib/channel";
import {Router} from "#angular/router";
import {AuthService} from "./auth.service";
#Injectable()
export class ChatService {
public chatClient: Client;
public currentChannel: Channel;
public chatConnectedEmitter: EventEmitter<any> = new EventEmitter<any>()
public chatDisconnectedEmitter: EventEmitter<any> = new EventEmitter<any>()
constructor(
private router: Router,
private authService: AuthService,
) { }
connect(token) {
Twilio.Client.create(token).then( (client: Client) => {
this.chatClient = client;
this.chatConnectedEmitter.emit(true);
}).catch( (err: any) => {
this.chatDisconnectedEmitter.emit(true);
if( err.message.indexOf('token is expired') ) {
localStorage.removeItem('twackToken');
this.router.navigate(['/']);
}
});
}
getPublicChannels() {
return this.chatClient.getPublicChannelDescriptors();
}
getChannel(sid: string): Promise<Channel> {
return this.chatClient.getChannelBySid(sid);
}
createChannel(friendlyName: string, isPrivate: boolean=false) {
return this.chatClient.createChannel({friendlyName: friendlyName, isPrivate: isPrivate, uniqueName: Util.guid()});
}
}
component:
ngOnInit() {
this.isConnecting = true;
this.chatService.connect(localStorage.getItem('twackToken'));
this.conSub = this.chatService.chatConnectedEmitter.subscribe( () => {
this.isConnected = true;
this.isConnecting = false;
this.getChannels();
this.chatService.chatClient.on('channelAdded', () => {
this.getChannels();
});
this.chatService.chatClient.on('channelRemoved', () => {
this.getChannels();
});
this.chatService.chatClient.on('tokenExpired', () => {
this.authService.refreshToken();
});
})
this.disconSub = this.chatService.chatDisconnectedEmitter.subscribe( () => {
this.isConnecting = false;
this.isConnected = false;
});
}
I want to write a TypeScript Declaration for ReactMeteorData.jsx which exports:
export default function connect(options) {
let expandedOptions = options;
if (typeof options === 'function') {
expandedOptions = {
getMeteorData: options,
};
}
const { getMeteorData, pure = true } = expandedOptions;
const BaseComponent = pure ? ReactPureComponent : ReactComponent;
return (WrappedComponent) => (
class ReactMeteorDataComponent extends BaseComponent {
...
}
);
}
Which is repacked as withTracker by react-meteor-data.jsx:
export { default as withTracker } from './ReactMeteorData.jsx';
I can simply declare the return value as Function:
declare module 'meteor/react-meteor-data' {
import * as React from 'react';
export function withTracker(func: () => {}): Function;
...
}
How can I declare what arguments and returns the Function creates without the need to change something in the origin package? So I would like to do something like:
export function withTracker(func: () => {}): (React.Component) => { React.Component };
Usage of the code is like this:
import * as React from 'react';
import { withTracker } from 'meteor/react-meteor-data';
class Header extends React.Component<any,any> {
render() {
return "test";
}
}
export default withTracker(() => {
return { user: 1 };
})(Header);
Thank you!
The type you describe could be written like this:
(c: React.Component) => React.Component
In the section declare module:
export function withTracker(func: () => {}): (c: React.Component) => React.Component;