Angular ngrx store testing `The feature name "storeOne" does not exist in the state` - angular8

After I gone through the below video for ngrx isolated testing:
John Crowson - Using MockStore in NgRx 8 | AngularUP
I tried to implement the same with my simple project. But I am getting error which I am not able to understand. any one help me to get solved?
it's very big help for me.
test ts file:
import { async, ComponentFixture, TestBed } from '#angular/core/testing';
import { provideMockStore, MockStore } from '#ngrx/store/testing';
import { ShellHomeComponent } from './shell-home.component';
import { StoreOne } from './../../models';
import { Store, select } from '#ngrx/store';
import { cold } from 'jasmine-marbles';
describe('ShellHomeComponent', () => {
let component: ShellHomeComponent;
let fixture: ComponentFixture<ShellHomeComponent>;
let mockStore: MockStore<StoreOne>;
const loadingState = {
loading: true,
items: [{ name: '1' }]
} as StoreOne;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ShellHomeComponent ],
imports: [],
providers: [provideMockStore({initialState: loadingState})]
})
.compileComponents();
mockStore = TestBed.get(Store);
}));
beforeEach(() => {
fixture = TestBed.createComponent(ShellHomeComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it('should display loading as true', () => {
const expected = cold('loading', { loading: false, items: [{ name: '3' }] });
expect(component.loading).toBeObservable(expected);
});
});
after run I am getting the following error:
ShellHomeComponent › should display loading as true
expect(received).toEqual(expected) // deep equality
- Expected
+ Received
Array [
Object {
"frame": 0,
"notification": Notification {
- "error": undefined,
- "hasValue": true,
- "kind": "N",
- "value": true,
- },
- },
- Object {
- "frame": 10,
- "notification": Notification {
- "error": undefined,
+ "error": [TypeError: Cannot read property 'loading' of undefined],
"hasValue": false,
- "kind": "C",
+ "kind": "E",
"value": undefined,
},
},
]
41 | it('should display loading as true', () => {
42 | const expected = cold('a|', { a: true });
> 43 | expect(component.loading).toBeObservable(expected);
| ^
44 | });
45 |
46 | });
at compare (node_modules/jasmine-marbles/bundles/jasmine-marbles.umd.js:379:33)
at src/app/module1/shell/shell-home/shell-home.component.spec.ts:43:35
console.warn node_modules/#ngrx/store/bundles/store.umd.js:608
The feature name "storeOne" does not exist in the state, therefore createFeatureSelector cannot access it. Be sure it is imported in a loaded module using StoreModule.forRoot('storeOne', ...) or StoreModule.forFeature('storeOne', ...). If the default state is intended to be undefined, as is the case with router state, this development-only warning message can be ignored.
Test Suites: 1 failed, 1 total
Tests: 1 failed, 1 total
Snapshots: 0 total
Time: 6.321s

I had a similar problem. My tests were failing because state in my reducer was undefined. I was also getting a warning in the console that The feature name "my-feature" does not exist in the state's root, therefore createFeatureSelector cannot access it. Be sure it is imported in a loaded module using StoreModule.forRoot('my-feature', ...) or StoreModule.forFeature('my-feature', ...).
The problem was that I was providing the mock store for the feature when I needed to provide the mock store for the entire app.
Try changing provideMockStore({initialState: loadingState}) to something like provideMockStore<State>({initialState: {shellComponent: loadingState}}) where State is the name of your application's global state (make sure that you import State from your application's state.ts file, not #ngrx/store), and shellComponent is the name of the feature you're testing.

To build off Danny's answer, you will do this:
providers: [
provideMockStore({
initialState: {
'addInvestigationModal': initialState
}
})
]
However, I still had an error An error was thrown in afterAll
error properties: Object({ longStack: 'TypeError: Cannot read property 'property_name' of undefined.
I fixed this by adding
afterEach(() => {
fixture.destroy();
});

I was getting this same warning as #Danny:
The feature name "some-feature" does not exist in the state's root, therefore createFeatureSelector cannot access it. Be sure it is imported in a loaded module using StoreModule.forRoot('some-feature', ...) or StoreModule.forFeature('some-feature', ...).
I forget that I had to add the module into the import list.
const someFeatureModule = StoreModule.forFeature('some-feature', someFeatureReducer);
...
#NgModule({
imports: [
someFeatureModule <-- this was missing
]
...

Related

Testing Angular 14 Standalone Components with Spectator

Our test runner is Jest.
Our component is marked as standalone: true,
If try to set up spectator like this:
describe('OurComponent', () => {
let spectator: Spectator<OurComponent>;
const fakeActivatedRoute: ActivatedRoute = {
snapshot: {data: {}},
} as ActivatedRoute;
const componentFactory: SpectatorFactory<OurComponent> = createComponentFactory({
component: OurComponent,
imports: [
// some imports
],
providers: [
// some providers
],
detectChanges: false,
shallow: true,
});
beforeEach(async () => {
spectator = componentFactory();
});
it('should be created', () => {
expect(spectator).toBeDefined();
});
});
Then we run into the following error:
"Error: Unexpected "OurComponent" found in the "declarations" array of the "TestBed.configureTestingModule" call, "OurComponent" is marked as standalone and can't be declared in any NgModule - did you intend to import it instead (by adding it to the "imports" array)?"
Using the Angular-CLI in order to generate resulted in a component with a test file which is built upon ComponentFixture.
How can we make it possible to test a standalone component using Spectator?
Depends on your spectator version (mine is 10.0.0) but you can use the declareComponent property :
const componentFactory: SpectatorFactory<OurComponent> = createComponentFactory({
component: OurComponent,
declareComponent: false,
});

How Do I Resolve this "An error was captured in current module: TypeError: e.parse is not a function"

How do I solve this Vue Js error on Shopware 6 Administration. The module is suppose to select a column in the database table.
PS. This is the complete code. I'm trying to read data from the database and view it in the twig template.
const { Component, Mixin } = Shopware;
const { Criteria } = Shopware.Data;
import template from './store-settings-page.html.twig'
Component.register('store-settings-page', {
template,
inject: [
'repositoryFactory'
],
metaInfo() {
return {
title: this.$createTitle()
};
},
data: function () {
return {
entity: undefined,
storeData: null,
entityId: '4e2891496c4e4587a3a7efe587fc8c80',
secret_key: 'hdkkjjsmk538dncbjmns',
public_key: '1destinoDet2123lefmoddfk##$$%O',
}
},
computed: {
storeKeysRepository() {
return this.repositoryFactory.create('store_keys');
},
},
created() {
this.storeKeysRepository
.get(this.entityId, Shopware.Context.api)
.then(entity => {
this.entity = entity;
});
console.log(entity);
},
});
Apologies if my knowledge of Vue & JS is a bit off, based on how I see Shopware codes it, I recommend data to be written like this:
data() {
return {
...
};
}
I would also try to strip your file to the bear minimum to see when the error disappears.
Another thing to check is if you are running a JS file or TS file. Maybe it's having a hard time parsing your file because you are extending store-settings-page and it assumes it should be TypeScript?
this.storeKeysRepository
.get(this.entityId, Shopware.Context.api)
.then(entity => {
this.entity = entity;
console.log(this.entity);
});
This will do the trick

NestJS testing controller can't resolve connection dependency

I wrote a test for a NestJS Controller that was working somehow, but now I get this error:
describe('ModalityController', () => {
let controller: ModalityController;
let modalitiesFactory: Modality[];
const mockService = {
getAll: jest.fn(),
createOne: jest.fn(),
updateOne: jest.fn(),
};
beforeAll(async (done) => {
await useSeeding();
modalitiesFactory = await factory(Modality)().makeMany(10);
done();
});
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [ModalityController],
providers: [
{
provide: 'Connection',
useValue: {},
},
{
provide: ModalityService,
useValue: mockService,
},
],
}).compile();
controller = module.get<ModalityController>(ModalityController);
});
it('should be defined', () => {
expect(controller).toBeDefined();
});
});
I get this error:
ModalityController
× should be defined (21 ms)
● ModalityController › should be defined
Nest can't resolve dependencies of the de8e6b44-c5c0-4633-b3b4-638e9df1b2a3 (?). Please make sure that the argument Connection at index [0] is available in the RootTestModule context.
Potential solutions:
- If Connection is a provider, is it part of the current RootTestModule?
- If Connection is exported from a separate #Module, is that module imported within RootTestModule?
#Module({
imports: [ /* the Module containing Connection */ ]
})
at Injector.lookupComponentInParentModules (../node_modules/#nestjs/core/injector/injector.js:193:19)
at Injector.resolveComponentInstance (../node_modules/#nestjs/core/injector/injector.js:149:33)
at resolveParam (../node_modules/#nestjs/core/injector/injector.js:103:38)
at async Promise.all (index 0)
at Injector.resolveConstructorParams (../node_modules/#nestjs/core/injector/injector.js:118:27)
at Injector.loadInstance (../node_modules/#nestjs/core/injector/injector.js:47:9)
at Injector.loadInjectable (../node_modules/#nestjs/core/injector/injector.js:65:9)
at async Promise.all (index 2)
at InstanceLoader.createInstancesOfInjectables (../node_modules/#nestjs/core/injector/instance-loader.js:62:9)
at ../node_modules/#nestjs/core/injector/instance-loader.js:30:13
● ModalityController › should be defined
expect(received).toBeDefined()
Received: undefined
46 |
47 | it('should be defined', () => {
> 48 | expect(controller).toBeDefined();
| ^
49 | });
50 |
51 | /*
at Object.<anonymous> (modality/modality.controller.spec.ts:48:24)
Test Suites: 1 failed, 1 total
Tests: 1 failed, 1 total
Snapshots: 0 total
Time: 5.604 s
I also tried to load the Modality Service and then provide a mock of the Modality Repository:
providers: [
ModalityService,
{
provide: getRepositoryToken(Modality),
useValue: mockRepository,
},
],
But no luck. I don't know how to provide a mocking connection object. What part of the controller is requiring the connection if this is the service job?
Help me guys. What can you see?
EDIT: Adding the controller code:
#ApiTags('Modalidad')
#Controller('modality')
export class ModalityController {
constructor(private modalityService: ModalityService) {}
#ApiOperation({
summary: 'Lista de todas las modalidades, paginados',
})
#OpenApiPaginationResponse(UpdateModalityDto)
#SkipJwtAuth()
#Get()
index(#Query() { items_per_page, page }: PaginationDto) {
return this.modalityService.getAll({
items_per_page: items_per_page || 10,
page: page || 0,
sortOrder: 'ASC',
});
}
#ApiOperation({
summary: 'obtiene una modalidad a partir de una id',
})
#ApiParam({
name: 'id',
type: Number,
})
#SkipJwtAuth()
#OpenApiTransformResponse(UpdateModalityDto)
#UseInterceptors(TransformInterceptor)
#Get(':id')
getOne(#Param('id', ParseIntPipe, EntityPipe()) modality: Modality) {
return modality;
}
#ApiOperation({
summary: 'Crear una nueva modalidad',
})
#SkipJwtAuth()
#OpenApiTransformResponse(UpdateModalityDto, 201)
#UseInterceptors(TransformInterceptor)
#Post()
async store(#Body() modality: CreateModalityDto) {
return await this.modalityService.createOne(modality);
}
#ApiOperation({
summary: 'actualizar una modalidad que ya existe',
})
#ApiParam({
name: 'id',
type: Number,
})
#SkipJwtAuth()
#OpenApiTransformResponse(UpdateModalityDto)
#UseInterceptors(TransformInterceptor)
#InjectItemToBody({ property: 'id' })
#Put(':id')
async update(
#Param('id', ParseIntPipe, EntityPipe()) modality: Modality,
#Body() updatedModality: UpdateModalityDto,
) {
return await this.modalityService.updateOne(modality, updatedModality);
}
}
SOLVED
The problem was that was not detecting the 'Connection' as a valid value. i've change it to the Connection object from the typeorm package

TypeError: Cannot read property 'cache' of undefined - VueJS

I created a Vue component which exports an async function. This component acts as a wrapper for calling my API. It's based on axios with a caching component that relies on localforage for some short lived persistence.
import localforage from 'localforage'
import memoryDriver from 'localforage-memoryStorageDriver'
import { setup } from 'axios-cache-adapter'
export default {
async cache() {
// Register the custom `memoryDriver` to `localforage`
await localforage.defineDriver(memoryDriver)
// Create `localforage` instance
const store = localforage.createInstance({
// List of drivers used
driver: [
localforage.INDEXEDDB,
localforage.LOCALSTORAGE,
memoryDriver._driver
],
// Prefix all storage keys to prevent conflicts
name: 'tgi-cache'
})
// Create `axios` instance with pre-configured `axios-cache-adapter` using a `localforage` store
return setup({
// `axios` options
baseURL: 'https://my.api',
cache: {
maxAge: 2 * 60 * 1000, // set cache time to 2 minutes
exclude: { query: false }, // cache requests with query parameters
store // pass `localforage` store to `axios-cache-adapter`
}
})
}
}
Here is how I am importing and using this component in my views:
import api from '#/components/Api.vue'
export default {
data() {
return {
userId: this.$route.params.id,
userData: ''
}
},
methods: {
loadClient(userId) {
const thisIns = this;
api.cache().then(async (api) => {
const response = await api.get('/client/find?id='+userId)
thisIns.userData = response.data.data[0]
}).catch(function (error) {
console.log(error)
})
},
},
created() {
this.loadClient(this.userId)
},
}
I can import this component and everything appears to work. I get data back from my API. However, immediately after every call, I get an error:
TypeError: Cannot read property 'cache' of undefined
Which references this line:
api.cache().then(async (api) => {
I am unable to understand why this is happening, or what it means. The error itself indicates that the component I am importing is undefined, though that's clearly not the case; if it were, the API call would ultimately fail I would suspect. Instead, I am lead to believe that perhaps I am not constructing/exporting my async cache() function properly.
Upon further review, I don't actually understand why the author has implemented it the way he has. Why would you want to create an instance of localForage every single time you make an API call?
I've opted not to use a component and to only instantiate an instance of localForage once.
main.js
import localforage from 'localforage'
import memoryDriver from 'localforage-memoryStorageDriver'
import { setup } from 'axios-cache-adapter'
// Register the custom `memoryDriver` to `localforage`
localforage.defineDriver(memoryDriver)
// Create `localforage` instance
const localforageStore = localforage.createInstance({
// List of drivers used
driver: [
localforage.INDEXEDDB,
localforage.LOCALSTORAGE,
memoryDriver._driver
],
// Prefix all storage keys to prevent conflicts
name: 'my-cache'
})
Vue.prototype.$http = setup({
baseURL: 'https://my.api',
cache: {
maxAge: 2 * 60 * 1000, // set cache time to 2 minutes
exclude: { query: false }, // cache requests with query parameters
localforageStore // pass `localforage` store to `axios-cache-adapter`
}
})
the view
export default {
data() {
return {
userId: this.$route.params.id,
userData: ''
}
},
methods: {
loadClient(userId) {
const thisIns = this;
thisIns.$http.get('/client/find?id='+userId)
.then(async (response) => {
thisIns.userData = response.data.data[0]
})
.catch(function (error) {
console.log(error)
})
},
},
created() {
this.loadClient(this.userId)
},
}

Jest - testing redux actions

I'm trying to test my app's redux actions using Jest. I've looked at the testing site # redux.js.org and other forums posts but I can't see why I'm getting the error I am, I think I'm not getting how the mocking works.
My action is in index.js:
export const setResponse = (res) => {
return {
type: 'RESPONSE_RECEIVED',
payload: res
}
};
My test is actions.test.js:
import * as actions from '../src/client/scripts/actions/index'
describe('actions', () => {
it('should create an action to receive a response', () => {
const payload = {response: 'solr_json'};
const expectedAction = {
type: 'RESPONSE_RECEIVED',
payload
}
expect(actions.setResponse(payload)).toEqual(expectedAction)
})
});
I got the error 'Expected undefined to equal Object...' soI thought actions.setResponse didn't exist, so I printed out actions.setResponse and it looks like this:
{ [Function: setResponse]
_isMockFunction: true,
getMockImplementation: [Function],
mock: { calls: [], instances: [] },
mockClear: [Function],
mockReturnValueOnce: [Function],
mockReturnValue: [Function],
mockImplementationOnce: [Function],
mockImpl: [Function],
mockImplementation: [Function],
mockReturnThis: [Function] }
So it seems the function is there, how do I actually call the function inside the Jest test? Even if I change
export const setResponse = (res) =>
to
export function setResponse(res)
(so it's the same format of the redux.js.org tutorial) I get the same error. For reference this is the jest part of my package.json:
"jest": {
"scriptPreprocessor": "node_modules/babel-jest",
"testFileExtensions": [
".test.js"
],
"testPathDirs": [
"__tests__"
],
"moduleFileExtensions": [
"js"
],
"unmockedModulePathPatterns": [
"node_modules/react",
"node_modules/react-addons-test-utils",
"node_modules/react-dom"
]
}
Thanks for any help
The problem seems that the module you want to test is mocked, cause you use unmockedModulePathPatterns. From the docs:
An array of regexp pattern strings that are matched against all
modules before the module loader will automatically return a mock for
them. If a module's path matches any of the patterns in this list, it
will not be automatically mocked by the module loader.
I would guess that if you remove this line the module is not automatically mocked. Normally its easier to mock the stuff that you want to mocked directly in your test using jest.mock. Or you add your source folder to the list of unmockedModulePathPatterns.