I am new to unit testing in vue 3 class component. I getting error says store is undefined. Here is my code in Home.vue file.
<script lang="ts">
import { Options, Vue } from "vue-class-component";
import HelloWorld from "#/components/HelloWorld.vue";
import { useStore } from "vuex";
import { key } from "#/store";
import { ProductType } from "#/types/commonTypeDefinitions";
#Options({
components: {
HelloWorld,
},
})
export default class Home extends Vue {
store = useStore(key);
get getAllProducts() {
return this.store.state.products ? this.store.state.products.groups : null;
}
mounted() {
if (!this.store.state.products) {
this.store.dispatch("getJsonData");
}
}
goToDetail(item: ProductType) {
localStorage.setItem("productDetail", JSON.stringify(item));
this.store.commit("setProductDetail", item);
const name = item.name.replaceAll(" ", "-");
console.log(name);
this.$router.push("/detail/" + name);
}
}
</script>
I am using jest for testing. Please help me with this.Thanks.
Related
component file:
// Angular and 3rd party libs imports
import { ChangeDetectionStrategy, Component, OnInit } from '#angular/core';
import { Store } from '#ngrx/store';
import { UntilDestroy, untilDestroyed } from '#ngneat/until-destroy';
// Utils
import { ApiLoadInfo, ApiStateEnum } from 'src/app/shared/utils/states';
// Services
import { TestPortalService } from '../../../testportal.service';
import { SharedClient } from 'src/app/shared/services/shared.service';
// Redux
import {
CandidateInstructionsState,
Quiz,
Instruction,
PageEnum,
LandingPageData
} from '../redux/candidate-instructions.state';
import * as instructionActions from '../redux/candidate-instructions.action';
import * as instructionSelects from '../redux/candidate-instructions.selector';
import { ActivatedRoute } from '#angular/router';
#UntilDestroy()
#Component({
selector: 'candidate-instructions-landing',
templateUrl: './instructions-landing.component.html',
styleUrls: ['./instructions-landing.component.scss', '../common.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class CandidateInstructionsLandingComponent implements OnInit {
// Exposing constants to html template
ApiStateEnum = ApiStateEnum;
PageEnum = PageEnum;
// Variables
initDataLoadState: ApiLoadInfo;
data: LandingPageData;
constructor(private _store: Store<CandidateInstructionsState>,
private _activatedRoute: ActivatedRoute,
private _testPortalService: TestPortalService,
) {
_store
.select(instructionSelects.selectInitDataLoadState)
.pipe(untilDestroyed(this))
.subscribe((initDataLoadState) => {
console.log('is same ref?:', this.initDataLoadState === initDataLoadState)
this.initDataLoadState = initDataLoadState;
console.log(initDataLoadState)
console.log('----------')
});
_store
.select(instructionSelects.selectLandingData)
.pipe(untilDestroyed(this))
.subscribe((data) => {
this.data = data;
});
}
ngOnInit() {
this.loadInstructions();
}
loadInstructions() {
this._store.dispatch(instructionActions.setInitData()); // sets state to 'loading'
this._testPortalService.getTestInstructions(
this._activatedRoute.snapshot.params.quizOrInviteId,
(error, response) => {
if (error) {
// sets state to 'error'
this._store.dispatch(instructionActions.setInitDataFail({ errmsg: error.toString() }));
} else {
// sets state to 'loaded'
this._store.dispatch(instructionActions.setInitDataSuccess({ instructions: response }));
console.log(response);
}
}
);
}
}
html:
{{ initDataLoadState.state }}
console output:
ui:
I thought when onPush is set, the template will re-render if the variable ref is changed. And since redux store is immutable that is always supposed to happen (confirmed by logging in the console). But still the actual component data is not in sync with the UI ie. component value = "loaded" but value in ui = "loading". Why is it so?
If you don't want to or can't use the pushPipe you could do something like this to subscribe to the store data:
import { Component, OnDestroy, OnInit } from '#angular/core';
import { Subscription } from 'rxjs';
import { Store } from '#ngrx/store';
import { getData } from 'path/to/store';
import { YourType } from 'path/to/type';
#Component({
selector: 'subscribing-component',
templateUrl: './subscribing.component.html'
})
export class SubscribingComponent implements OnInit, OnDestroy {
data: YourType;
dataSubscription: Subscription;
constructor(store: Store) {}
ngOnInit(): void {
this.dataSubscription = this.store.select(getData).subscribe((data) => {
this.data = data;
});
}
// don't forget to unsubscribe
ngOnDestroy(): void {
if (this.dataSubscription) {
this.dataSubscription.unsubscribe();
}
}
}
I'm asking because I don't have an example.
To declare class, export, and import
What should I do?
test.js
export default class {
test() {
alert("ABC")
}
}
Main.vue
import exam from '../../test.js'
export default {
setup() {
exam.test()
}
}
import exam from '../../test.js'
import { ref } from 'vue'
export default {
setup() {
const class = ref(new exam())
}
}
i am using asp.net core web api for backend and angular 7 for front end .i created database using code first
approach and then i added one more table called Complains .now i wan to return complains table id and two or three more columns from complains table using get request. then get these values in angular and show some where .
//this is interface method
Object UserComplainInformation(Complains complains);
//this is service class which implements above interface
public Object UserComplainInformation(Complains complains)
{
var resp = new
{
Id = _appDbContext.Complains.FindAsync(complains.Id),
Type =complains.Type
};
try
{
_appDbContext.Complains.FindAsync(resp);
return resp;
}
catch(Exception ex)
{
throw ex;
}
//Controller
[HttpGet]
// [Route("complainInformation")]
public Object UserComplainInformation(Complains complain)
{
return _complains.UserComplainInformation(complain);
}
//angular service code
import { Injectable } from '#angular/core';
import { ToastrService } from 'ngx-toastr';
import { ConfigService } from './util/config.service';
import { HttpClient } from '#angular/common/http';
#Injectable({
providedIn: 'root'
})
export class ComplainHistoryService {
BaseUrl : string ='';
constructor( private config:ConfigService, private http:HttpClient) {
this.BaseUrl =config.getApiURI();
}
ngOnInit(){ }
getUserComplainHistory(){
return this.http.get(this.BaseUrl +'/complianInformation');
}
}
//.ts file usercomplainhistory
import { Component, OnInit } from '#angular/core';
import { Router } from '#angular/router';
import { ComplianHistoryService } from 'src/shared/complain-history.service';
#Component({
selector: 'app-user-complians-history',
templateUrl: './user-complains-history.component.html',
styles: []
})
export class UserComplainsHistoryComponent implements OnInit {
userDetails = sessionStorage.getItem('FullName');
userComplainDetails;
constructor(private router:Router, private complainService: ComplainHistoryService) { }
ngOnInit() {
this.complainService.getUserComplainHistory().subscribe(
res =>{
this.userComplainDetails = res;
console.log(res);
},
err =>{
console.error(err);
}
)
}
}
//this is html file where i want to show id and some more fields
<ul class="list-group">
<li class="list-group-item"><strong>FullName : </strong>{{userDetails}}</li>
<li class="list-group-item"><strong>Complian Id : </strong>{{userComplianDetails}}</li>
</ul>
I am new to Ionic and I have a problem trying to push a rootpage on Ionic 3
On app.component.ts
import { Component } from '#angular/core';
import { LoginPage } from '../pages/login/login';
import { LoggedinPage } from '../pages/loggedin/loggedin';
import firebase from 'firebase';
#Component({
template: `<ion-nav [root]="rootPage"></ion-nav>`
})
export class MyApp {
rootPage: any;
var state = firebase.auth().onAuthStateChanged(function(user) {
if (user) {
this.rootPage = LoginPage;
//console.log(this.rootPage);
//from here i can see that the this.rootpage is defined.
} else {
this.rootPage = LoggedinPage;
}
console.log(this.rootPage);
//the rootpage is not defined outside of the funtion
});
}
What I want to do, id to redirect users that are already loggedin to the LoggedIn Page.
in app.component.ts
rootPage: any; is mistake, can you use rootPage: any = 'targetPage';
if you use menu rootPage: any = 'menuPage'; and chose rootPage in menuPage.ts ;
export class MenuPage {
rootPage = 'targetPage';
Need to change code following manner:
import {Component, ViewChild} from '#angular/core';
import {Nav} from 'ionic-angular';
import { LoginPage } from '../pages/login/login';
import { LoggedinPage } from '../pages/loggedin/loggedin';
import firebase from 'firebase';
#Component({
template: `<ion-nav [root]="rootPage"></ion-nav>`
})
export class MyApp {
rootPage: any;
#ViewChild(Nav) nav: Nav;
var state = firebase.auth().onAuthStateChanged(function(user) {
if (user) {
this.nav.setRoot(LoginPage);
//console.log(this.rootPage);
//from here i can see that the this.rootpage is defined.
} else {
this.nav.setRoot(LoggedinPage);
}
console.log(this.rootPage);
//the rootpage is not defined outside of the funtion
});
}
You should set userdata after login and clear on logout. and while setting rootPage you can check whether userdata does exist or not. And on initializeApp function of app.component.ts
initializeApp() {
this.platform.ready().then(() => {
this.rootPage = localStorage.getItem('userData') ? MyDashboardPage : LoginPage;
});
}
I am trying to understand how decorators work with Meteor 1.4. From what I read, this feature is supported.
Now, I am unsure how to actually implement it. From this blog, to decorate a class, I would require this code
export const TestDecorator = (target) => {
let _componentWillMount = target.componentWillMount;
target.componentWillMount = function () {
console.log("*** COMPONENT WILL MOUNT");
_componentWillMount.call(this, ...arguments);
}
return target;
}
Then use it as
import React, { Component } from 'react';
import { TestDecorator } from 'path/to/decorator.js';
#TestDecorator
export default class FooWidget extends Component {
//...
}
The code compiles, but nothing gets output when the component is being rendered.
What am I missing? How do I implement a decorator in Meteor? Is this the proper solution? What is the alternative?
Edit
I have tried this, and it still does not work
export const TestDecorator = (target) => {
console.log("*** THIS IS NOT EVEN DISPLAYED! ***");
target.prototype.componentWillMount = function () {
// ...
};
}
You are assigning your componentWillMount function to the class FooWidget instead of its prototype. Change that to target.prototype.componentWillMount = …. Besides, storing the previous componentWillMount is unnecessary in this case because it is undefined anyway.
Here is a full working example:
main.html
<head>
<title>decorators</title>
</head>
<body>
<div id="root"></div>
</body>
decorator.js
export const TestDecorator = (target) => {
console.log('Decorating…');
target.prototype.componentWillMount = function() {
console.log('Component will mount');
};
};
main.jsx
import React, { Component } from 'react';
import { render } from 'react-dom';
import { TestDecorator } from '/imports/decorator.js';
import './main.html';
#TestDecorator
class FooWidget extends Component {
render() {
return <h1>FooWidget</h1>;
}
}
Meteor.startup(function() {
render(<FooWidget/>, document.getElementById('root'));
});
.babelrc
{
"plugins": ["transform-decorators-legacy"]
}