Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a test for currentUser and not user?

What is returned when the user is not a user?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a test for currentUser and not user?

I have added it to last commit

What is returned when the user is not a user?

true - to not show tos banner if user is not loggined in

Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { Store } from '@ngxs/store';

import { MockComponent } from 'ng-mocks';

import { of } from 'rxjs';

import { ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';

Expand All @@ -16,13 +18,15 @@ import { TranslationServiceMock } from '@testing/mocks/translation.service.mock'
import { OSFTestingStoreModule } from '@testing/osf.testing.module';
import { provideMockStore } from '@testing/providers/store-provider.mock';

describe('Component: Tos Consent Banner', () => {

describe('TosConsentBannerComponent', () => {
let component: TosConsentBannerComponent;
let fixture: ComponentFixture<TosConsentBannerComponent>;
let store: Store;
let store: jest.Mocked<Store>;

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [OSFTestingStoreModule, TosConsentBannerComponent, MockComponent(IconComponent)],
imports: [TosConsentBannerComponent, OSFTestingStoreModule, MockComponent(IconComponent)],
providers: [
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prune

provideMockStore({
signals: [{ selector: UserSelectors.getCurrentUser, value: MOCK_USER }],
Expand All @@ -32,7 +36,9 @@ describe('Component: Tos Consent Banner', () => {
}).compileComponents();

fixture = TestBed.createComponent(TosConsentBannerComponent);
store = TestBed.inject(Store);
store = TestBed.inject(Store) as jest.Mocked<Store>;
component = fixture.componentInstance;
store.dispatch = jest.fn().mockReturnValue(of(undefined));
fixture.detectChanges();
});

Expand All @@ -50,7 +56,6 @@ describe('Component: Tos Consent Banner', () => {
});

it('should dispatch AcceptTermsOfServiceByUser action when "Continue" is clicked', () => {
jest.spyOn(store, 'dispatch');
const checkboxInput = fixture.debugElement.query(By.css('p-checkbox input')).nativeElement;
checkboxInput.click();
fixture.detectChanges();
Expand All @@ -61,4 +66,25 @@ describe('Component: Tos Consent Banner', () => {

expect(store.dispatch).toHaveBeenCalledWith(new AcceptTermsOfServiceByUser());
});

it('should return true for "acceptedTermsOfServiceChange" when user is null to not show banner', async () => {
await TestBed.resetTestingModule()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should just be pruned and just be the jest mock. Just make sure the mock is setup before the createComponent call.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have tried the following approach

it('should return true for "acceptedTermsOfServiceChange" when user is null to not show banner', async () => {
      const mockStore = TestBed.inject(Store) as jest.Mocked<Store>;

    jest.spyOn(mockStore, 'selectSnapshot').mockImplementation((selector: any) => {
      if (selector === UserSelectors.getCurrentUser) {
        return null;
      }
      return undefined;
  });
      const fixture = TestBed.createComponent(TosConsentBannerComponent);
      const component = fixture.componentInstance;

      fixture.detectChanges();
      expect(component.acceptedTermsOfServiceChange()).toBe(true);
    });

and it does not set the

image

.configureTestingModule({
imports: [TosConsentBannerComponent, OSFTestingStoreModule, MockComponent(IconComponent)],
providers: [
provideMockStore({
signals: [{ selector: UserSelectors.getCurrentUser, value: null }],
}),
TranslationServiceMock,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not needed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

],
})
.compileComponents();

const fixture = TestBed.createComponent(TosConsentBannerComponent);
const component = fixture.componentInstance;

fixture.detectChanges();
expect(component.acceptedTermsOfServiceChange()).toBe(true);
});

});
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { Button } from 'primeng/button';
import { Checkbox } from 'primeng/checkbox';
import { Message } from 'primeng/message';

import { Component, computed, signal } from '@angular/core';
import { Component, computed, inject, signal } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { RouterLink } from '@angular/router';

Expand Down Expand Up @@ -52,10 +52,16 @@ export class TosConsentBannerComponent {
/**
* Computed signal indicating whether the user has already accepted the Terms of Service.
*/
readonly acceptedTermsOfServiceChange = computed(() => {
const user = this.currentUser();
return user?.acceptedTermsOfService ?? false;
});
acceptedTermsOfServiceChange = computed(() =>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why no read only? That seems to be an Exoft pattern

Copy link
Contributor Author

@mkovalua mkovalua Sep 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have seen that computed was used without read only all over the project though there is read only too, I prefer not strict style if it is possible

image

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay

{
const user = this.currentUser()
/**
* if user is authenticated we check whether is accepted terms of service to hide banner or show if not
* otherwise user is not authenticated we hide banner always
*/
return user ? user.acceptedTermsOfService : true;
}
);

/**
* Triggered when the user clicks the Continue button.
Expand Down
3 changes: 2 additions & 1 deletion src/assets/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,8 @@
"and": " and ",
"privacyPolicy": " privacy policy.",
"haveReadAndAgree": "I've read and agree to the terms and conditions",
"continue": "Continue"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is strange, how did this originally get committed? No need to respond.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From what I see we prefer to use en.json to text from it, though it may look redundant for small text.

"continue": "Continue",
"errorMessage": "We were unable to save your consent."
},
"cookie-consent": {
"message": "Notice: This website relies on cookies to help provide a better user experience. By clicking accept or continuing to use the site, you consent to our use of cookies. See our Privacy Policy and Cookie Use for more information.",
Expand Down
Loading