Skip to content
Closed
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
54 changes: 29 additions & 25 deletions docs/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -1,37 +1,41 @@
_Any italic text should be deleted from the final Pull Request text, including this line_
## Jira ticket

# Description
Ticket number or link:

_Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change._
## Summary

Fixes # (issue)
Briefly explain what you changed and why.

## Type of change
## Target branch

_Please delete options that are not relevant._
Which shared branch should this be merged into?

- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] This change requires a documentation update
Example: `feature/email-notifications`

# How Has This Been Tested?
## Testing

_Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration_
Explain how you tested the change.

## Testing Checklist:
Include any useful commands, screenshots, logs, or test results.

- [ ] Tested in latest Chrome
- [ ] Tested in latest Safari
- [ ] Tested in latest Firefox
## Security and privacy

# Checklist:
Does this change affect authentication, permissions, notifications, student data,
secrets, personal information, or privacy?

- [ ] My code follows the style guidelines of this project
- [ ] I have formatted my changes with `npm run format`
- [ ] I have run `npm run lint` with no errors
- [ ] I have performed a self-review of my own code
- [ ] I have commented my code in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have requested a review from @macite and @jakerenzella on the Pull Request
If there is no known impact, write: `No known security or privacy impact.`

## Evidence

Add any screenshots, test output, diagrams, or other evidence that will help the reviewer.

## Checklist

- [ ] I selected the correct base branch.
- [ ] My changes match the assigned Jira ticket.
- [ ] I kept the change within the agreed scope.
- [ ] I tested my changes.
- [ ] I did not include passwords, tokens, API keys, secrets, or real student data.
- [ ] I updated relevant documentation, or no documentation change was needed.
- [ ] I reviewed my own changes before requesting review.
- [ ] This pull request is ready for review.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@

@if (!task || task.comments.length === 0) {
<div fxFlexFill fxLayout="column" fxLayoutAlign="center center">
<mat-icon id="noView">forum</mat-icon>
<mat-icon id="noView" aria-hidden="true">forum</mat-icon>
<p>No comments on this task yet.</p>
</div>
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,17 @@ const taskServiceStub = {
};
const emptyProvider = {};

const EMPTY_STATE_TEMPLATE = `
<div>
@if (!task || task.comments.length === 0) {
<div fxFlexFill fxLayout="column" fxLayoutAlign="center center">
<mat-icon id="noView" aria-hidden="true">forum</mat-icon>
<p>No comments on this task yet.</p>
</div>
}
</div>
`;

describe('TaskCommentsViewerComponent', () => {
let component: TaskCommentsViewerComponent;
let fixture: ComponentFixture<TaskCommentsViewerComponent>;
Expand All @@ -39,12 +50,36 @@ describe('TaskCommentsViewerComponent', () => {
.compileComponents();
});

beforeEach(() => {
it('should create', () => {
fixture = TestBed.createComponent(TaskCommentsViewerComponent);
component = fixture.componentInstance;
expect(component).toBeTruthy();
});

it('should create', () => {
expect(component).toBeTruthy();
it('renders empty-state text when there is no task or no comments', () => {
TestBed.overrideComponent(TaskCommentsViewerComponent, {
set: {template: EMPTY_STATE_TEMPLATE},
});
fixture = TestBed.createComponent(TaskCommentsViewerComponent);
component = fixture.componentInstance;
fixture.detectChanges();

const emptyIcon = fixture.nativeElement.querySelector('#noView');
const emptyText = fixture.nativeElement.querySelector('p');
expect(emptyIcon).toBeTruthy();
expect(emptyText.textContent).toContain('No comments on this task yet.');
});

it('does not render empty-state text when task has comments', () => {
TestBed.overrideComponent(TaskCommentsViewerComponent, {
set: {template: EMPTY_STATE_TEMPLATE},
});
fixture = TestBed.createComponent(TaskCommentsViewerComponent);
component = fixture.componentInstance;
component.task = {comments: [{}]} as any;
fixture.detectChanges();

const emptyIcon = fixture.nativeElement.querySelector('#noView');
expect(emptyIcon).toBeFalsy();
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,8 @@
}

<div class="center-task-list" [hidden]="loading || filteredTasks?.length !== 0 || isNarrow">
<mat-icon>done_all</mat-icon>
<mat-icon aria-hidden="true">done_all</mat-icon>
<p>No tasks match these filters.</p>
</div>

<!--/search-options-->
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import '@angular/compiler';
import {HotkeysService} from '@ngneat/hotkeys';
import {beforeEach, describe, expect, it} from 'vitest';
import {NO_ERRORS_SCHEMA} from '@angular/core';
import {ComponentFixture, TestBed} from '@angular/core/testing';
import {MatDialog} from '@angular/material/dialog';
import {ActivatedRoute, Router} from '@angular/router';
import {EMPTY} from 'rxjs';
import {UserService} from 'src/app/api/models/doubtfire-model';
import {TaskDefinitionService} from 'src/app/api/services/task-definition.service';
import {FileDownloaderService} from 'src/app/common/file-downloader/file-downloader.service';
Expand All @@ -16,9 +18,21 @@ import {StaffTaskListComponent} from './staff-task-list.component';

const hotkeysServiceStub = {
removeShortcuts: () => {},
getHotkeys: () => [],
addShortcut: () => ({subscribe: () => {}}),
};
const userServiceStub = {
currentUser: {name: 'Test User'},
};
const emptyProvider = {};

const EMPTY_STATE_TEMPLATE = `
<div class="center-task-list" [hidden]="loading || filteredTasks?.length !== 0 || isNarrow">
<mat-icon aria-hidden="true">done_all</mat-icon>
<p>No tasks match these filters.</p>
</div>
`;

describe('StaffTaskListComponent', () => {
let component: StaffTaskListComponent;
let fixture: ComponentFixture<StaffTaskListComponent>;
Expand All @@ -33,7 +47,7 @@ describe('StaffTaskListComponent', () => {
{provide: MatDialog, useValue: emptyProvider},
{provide: CsvUploadModalService, useValue: emptyProvider},
{provide: CsvResultModalService, useValue: emptyProvider},
{provide: UserService, useValue: emptyProvider},
{provide: UserService, useValue: userServiceStub},
{provide: HotkeysService, useValue: hotkeysServiceStub},
{provide: Router, useValue: emptyProvider},
{provide: ActivatedRoute, useValue: emptyProvider},
Expand All @@ -46,12 +60,65 @@ describe('StaffTaskListComponent', () => {
.compileComponents();
});

beforeEach(() => {
const setupComponentInputs = () => {
component.unit = {
tutorialsForUserName: () => [],
staff: [],
tutorials: [],
} as any;
component.unitRole = {role: 'Tutor', id: 1} as any;
component.taskData = {
source: () => EMPTY,
selectedTask: null,
taskKey: null,
onSelectedTaskChange: () => {},
taskDefMode: false,
} as any;
component.tasks = [];
};

it('should create', () => {
fixture = TestBed.createComponent(StaffTaskListComponent);
component = fixture.componentInstance;
expect(component).toBeTruthy();
});

it('should create', () => {
expect(component).toBeTruthy();
it('renders empty-state text when filtered task list is empty', () => {
TestBed.overrideComponent(StaffTaskListComponent, {
set: {template: EMPTY_STATE_TEMPLATE},
});
fixture = TestBed.createComponent(StaffTaskListComponent);
component = fixture.componentInstance;
setupComponentInputs();
fixture.detectChanges();

component.filteredTasks = [];
component.loading = false;
component.isNarrow = false;
fixture.detectChanges();

const container = fixture.nativeElement.querySelector('.center-task-list');
expect(container.hidden).toBe(false);

const emptyText = fixture.nativeElement.querySelector('.center-task-list p');
expect(emptyText.textContent).toContain('No tasks match these filters.');
});

it('does not render empty-state text when tasks are present', () => {
TestBed.overrideComponent(StaffTaskListComponent, {
set: {template: EMPTY_STATE_TEMPLATE},
});
fixture = TestBed.createComponent(StaffTaskListComponent);
component = fixture.componentInstance;
setupComponentInputs();
fixture.detectChanges();

component.filteredTasks = [{} as any];
component.loading = false;
component.isNarrow = false;
fixture.detectChanges();

const container = fixture.nativeElement.querySelector('.center-task-list');
expect(container.hidden).toBe(true);
});
});
});