After changing the the state from 'light' to 'dark' it's not gonna change it in component. It will keep the state as 'light' even though I have dispatched an action which is gonna change it to dark. Is there a way to detect it in component?
Here is the unit test file
app.component.spec.ts
describe('AppComponent', () => {
let component: AppComponent;
let fixture: ComponentFixture<AppComponent>;
let compiled: HTMLElement;
let store: MockStore;
const initialState = {
theme: fromTheme.initialState,
};
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [AppComponent],
imports: [AppRoutingModule],
providers: [provideMockStore({ initialState })],
}).compileComponents();
fixture = TestBed.createComponent(AppComponent);
component = fixture.componentInstance;
fixture.detectChanges();
compiled = fixture.debugElement.nativeElement;
store = TestBed.get<MockStore>(MockStore);
});
it('should create the app', () => {
expect(component).toBeTruthy();
});
it('should have a class with theme', () => {
expect(compiled.classList.contains('light')).toBeTrue();
store.dispatch(fromTheme.changeTheme({ payload: 'dark' }));
fixture.detectChanges();
expect(compiled.classList.contains('dark')).toBeTrue();
});
});
Here is the component file
app.component.ts
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
host: {
'[class.light]': 'theme === "light"',
'[class.dark]': 'theme === "dark"',
},
})
export class AppComponent implements OnInit, OnDestroy {
theme: ThemeType = 'light';
themeSubscription: Subscription | null = null;
constructor(
private store: Store<AppStore>,
) {}
ngOnInit() {
this.themeSubscription = this.store.select(selectTheme).subscribe((themeState) => {
this.theme = themeState.theme;
if (!themeState.isChanged) {
const preferredTheme = getPreferredTheme();
this.store.dispatch(changeTheme({ payload: preferredTheme }));
}
});
}
ngOnDestroy() {
this.themeSubscription?.unsubscribe();
}
}
There was no need to provide a mock store, instead of that, we can provide the real store like this
let store: Store<AppStore>;
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [AppComponent],
imports: [AppRoutingModule, StoreModule.forRoot(appReducer)],
});
fixture = TestBed.createComponent(AppComponent);
component = fixture.componentInstance;
fixture.detectChanges();
compiled = fixture.debugElement.nativeElement;
store = TestBed.get<Store>(Store);
});
Then the component will listen for changes in this store, and the dispatch will work.
Test Examples:
it('should have a class with theme', () => {
store.select(fromTheme.selectTheme)
.subscribe((themeState) => {
expect(compiled.classList.contains(themeState.theme)).toBeTrue();
});
});
it('should be able to dispatch the changeTheme', () => {
const newTheme = 'dark';
store.dispatch(fromTheme.changeTheme({ payload: newTheme }));
expect(compiled.classList.contains(newTheme)).toBeTrue();
});