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
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ <h2 mat-dialog-title class="dialog-icon-title">
<a mat-button [href]="urls.transceleratorImportHelpPage" target="_blank">{{ t("learn_more") }}</a>
@if (transceleratorRequest.status === "offline") {
<mat-error>
{{ t("no_transcelerator_offline") }}
{{ t("no_import_offline", { method: "Transcelerator" }) }}
</mat-error>
} @else if (transceleratorRequest.status === "trying" && transceleratorRequest.failedAttempts > 0) {
<mat-error>
Expand Down Expand Up @@ -112,6 +112,11 @@ <h2 mat-dialog-title class="dialog-icon-title">
{{ t("import_from_paratext") }}
</button>
<a mat-button [href]="urls.paratextImportHelpPage" target="_blank">{{ t("learn_more") }}</a>
@if (!isOnline) {
<mat-error>
{{ t("no_import_offline", { method: "Paratext" }) }}
</mat-error>
}
</mat-card-actions>
</mat-card>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -487,7 +487,7 @@ describe('ImportQuestionsDialogComponent', () => {
it('does not try to load transcelerator questions when the user is online', fakeAsync(() => {
const env = new TestEnvironment({ offline: true });
expect(env.importFromTransceleratorButton.disabled).toBe(true);
expect(env.errorMessages).toEqual(['Importing from Transcelerator is not available offline.']);
expect(env.errorMessages[0]).toEqual('Importing from Transcelerator is not available offline.');
env.setOnline(true);
expect(env.importFromTransceleratorButton.disabled).toBe(false);
expect(env.errorMessages).toEqual([]);
Expand All @@ -502,115 +502,131 @@ describe('ImportQuestionsDialogComponent', () => {
expect(env.overlayContainerElement.hasChildNodes()).withContext('close button closes dialog').toBeFalse();
}));

it('collects unique Paratext tags in alphabetical order', fakeAsync(() => {
const env = new TestEnvironment();
const tagAlpha: ParatextNoteTag = { id: 1, name: 'Alpha' };
const tagBeta: ParatextNoteTag = { id: 3, name: 'Beta' };
const tagGamma: ParatextNoteTag = { id: 2, name: 'Gamma' };
const notes: ParatextNote[] = [
{
id: 'note-1',
verseRef: 'MAT 1:1',
comments: [
{ verseRef: 'MAT 1:1', content: '<p>Alpha</p>', tag: tagGamma },
{ verseRef: 'MAT 1:1', content: '<p>Alpha again</p>', tag: tagAlpha }
]
},
{
id: 'note-2',
verseRef: 'MAT 1:2',
comments: [
{ verseRef: 'MAT 1:2', content: '<p>Beta</p>', tag: tagBeta },
{ verseRef: 'MAT 1:2', content: '<p>Beta duplicate</p>', tag: tagBeta }
]
}
];
describe('Import from Paratext', () => {
it('disables import button when user is offline', fakeAsync(() => {
const env = new TestEnvironment({ offline: true });
expect(env.importFromParatextButton.disabled).toBe(true);
expect(env.errorMessages[1]).toEqual('Importing from Paratext is not available offline.');

const tags = env.collectParatextTagOptions(env.component, notes);

expect(tags.length).toBe(3);
expect(tags.map(tag => tag.name)).toEqual(['Alpha', 'Beta', 'Gamma']);
expect(tags.map(tag => tag.id)).toEqual([1, 3, 2]);
}));
// simulate going back online
env.setOnline(true);
expect(env.importFromParatextButton.disabled).toBe(false);
}));

it('shows a message when no notes have tagged comments', fakeAsync(() => {
const env = new TestEnvironment();
const notes: ParatextNote[] = [
{
id: 'note-1',
verseRef: 'MAT 1:1',
comments: [{ verseRef: 'MAT 1:1', content: '<p>Note without tag</p>' }]
}
];
env.setParatextNotes(env.component, notes);
env.setParatextTagOptions(env.component, env.collectParatextTagOptions(env.component, notes));
env.component.questionSource = 'paratext';
env.component.showParatextTagSelector = true;
env.component.selectedParatextTagId = null;
env.component.errorState = undefined;

env.fixture.detectChanges();
tick();
it('collects unique Paratext tags in alphabetical order', fakeAsync(() => {
const env = new TestEnvironment();
const tagAlpha: ParatextNoteTag = { id: 1, name: 'Alpha' };
const tagBeta: ParatextNoteTag = { id: 3, name: 'Beta' };
const tagGamma: ParatextNoteTag = { id: 2, name: 'Gamma' };
const notes: ParatextNote[] = [
{
id: 'note-1',
verseRef: 'MAT 1:1',
comments: [
{ verseRef: 'MAT 1:1', content: '<p>Alpha</p>', tag: tagGamma },
{ verseRef: 'MAT 1:1', content: '<p>Alpha again</p>', tag: tagAlpha }
]
},
{
id: 'note-2',
verseRef: 'MAT 1:2',
comments: [
{ verseRef: 'MAT 1:2', content: '<p>Beta</p>', tag: tagBeta },
{ verseRef: 'MAT 1:2', content: '<p>Beta duplicate</p>', tag: tagBeta }
]
}
];

const tags = env.collectParatextTagOptions(env.component, notes);

expect(tags.length).toBe(3);
expect(tags.map(tag => tag.name)).toEqual(['Alpha', 'Beta', 'Gamma']);
expect(tags.map(tag => tag.id)).toEqual([1, 3, 2]);
}));

expect(env.component.status).toBe('paratext_tag_selection');
expect(env.getParatextTagMessage()).toBe('There are no tagged notes available to import.');
}));
it('shows a message when no notes have tagged comments', fakeAsync(() => {
const env = new TestEnvironment();
const notes: ParatextNote[] = [
{
id: 'note-1',
verseRef: 'MAT 1:1',
comments: [{ verseRef: 'MAT 1:1', content: '<p>Note without tag</p>' }]
}
];
env.setParatextNotes(env.component, notes);
env.setParatextTagOptions(env.component, env.collectParatextTagOptions(env.component, notes));
env.component.questionSource = 'paratext';
env.component.showParatextTagSelector = true;
env.component.selectedParatextTagId = null;
env.component.errorState = undefined;

env.fixture.detectChanges();
tick();

expect(env.component.status).toBe('paratext_tag_selection');
expect(env.getParatextTagMessage()).toBe('There are no tagged notes available to import.');
}));

it('converts Paratext notes for the selected tag into questions', fakeAsync(() => {
const tagQuestions: ParatextNoteTag = { id: 7, name: 'Questions' };
const notes: ParatextNote[] = [
{
id: 'note-1',
verseRef: 'MAT 1:1',
comments: [
{ verseRef: 'MAT 1:1', content: '<p>Ignore</p>', tag: { id: 6, name: 'Other' } },
{ verseRef: 'MAT 1:1', content: ' <p>Question <strong>text</strong></p> ', tag: tagQuestions }
]
},
{
id: 'note-2',
verseRef: 'MAT 1:2',
comments: [{ verseRef: 'MAT 1:2', content: '<p>Question 2</p>', tag: tagQuestions }]
},
{
id: 'note-3',
verseRef: 'GEN 1:1',
comments: [{ verseRef: 'GEN 1:1', content: '<p>Different book</p>', tag: tagQuestions }]
}
];
const preexistingQuestion = TestEnvironment.createQuestionDocWithSource('note-1', new VerseRef('MAT 1:1'), 'text');
const env = new TestEnvironment({ existingQuestions: [preexistingQuestion], paratextNotes: notes });
env.setParatextNotes(env.component, notes);
env.setParatextTagOptions(env.component, env.collectParatextTagOptions(env.component, notes));
env.component.selectedParatextTagId = tagQuestions.id;
env.component.questionSource = 'paratext';
env.component.showParatextTagSelector = true;

void env.component.confirmParatextTagSelection();
tick();
env.fixture.detectChanges();

expect(env.component.status).toBe('filter_notes');
expect(env.component.filteredList.length).toBe(2);
const questionAlreadyImported = env.component.filteredList[0];
expect(questionAlreadyImported.question.id).toBe('note-1');
expect(questionAlreadyImported.question.text).toBe('Question text');
expect(questionAlreadyImported.sfVersionOfQuestion).not.toBeUndefined();

expect(env.component.showDuplicateImportNote).toBeFalse();
questionAlreadyImported.checked = true;
expect(env.component.showDuplicateImportNote).toBeTrue();
}));
it('converts Paratext notes for the selected tag into questions', fakeAsync(() => {
const tagQuestions: ParatextNoteTag = { id: 7, name: 'Questions' };
const notes: ParatextNote[] = [
{
id: 'note-1',
verseRef: 'MAT 1:1',
comments: [
{ verseRef: 'MAT 1:1', content: '<p>Ignore</p>', tag: { id: 6, name: 'Other' } },
{ verseRef: 'MAT 1:1', content: ' <p>Question <strong>text</strong></p> ', tag: tagQuestions }
]
},
{
id: 'note-2',
verseRef: 'MAT 1:2',
comments: [{ verseRef: 'MAT 1:2', content: '<p>Question 2</p>', tag: tagQuestions }]
},
{
id: 'note-3',
verseRef: 'GEN 1:1',
comments: [{ verseRef: 'GEN 1:1', content: '<p>Different book</p>', tag: tagQuestions }]
}
];
const preexistingQuestion = TestEnvironment.createQuestionDocWithSource(
'note-1',
new VerseRef('MAT 1:1'),
'text'
);
const env = new TestEnvironment({ existingQuestions: [preexistingQuestion], paratextNotes: notes });
env.setParatextNotes(env.component, notes);
env.setParatextTagOptions(env.component, env.collectParatextTagOptions(env.component, notes));
env.component.selectedParatextTagId = tagQuestions.id;
env.component.questionSource = 'paratext';
env.component.showParatextTagSelector = true;

void env.component.confirmParatextTagSelection();
tick();
env.fixture.detectChanges();

expect(env.component.status).toBe('filter_notes');
expect(env.component.filteredList.length).toBe(2);
const questionAlreadyImported = env.component.filteredList[0];
expect(questionAlreadyImported.question.id).toBe('note-1');
expect(questionAlreadyImported.question.text).toBe('Question text');
expect(questionAlreadyImported.sfVersionOfQuestion).not.toBeUndefined();

expect(env.component.showDuplicateImportNote).toBeFalse();
questionAlreadyImported.checked = true;
expect(env.component.showDuplicateImportNote).toBeTrue();
}));

it('shows an error when no Paratext project can be found', fakeAsync(() => {
const env = new TestEnvironment({ paratextProjects: [], paratextNotes: [] });
it('shows an error when no Paratext project can be found', fakeAsync(() => {
const env = new TestEnvironment({ paratextProjects: [], paratextNotes: [] });

env.click(env.importFromParatextButton);
env.click(env.importFromParatextButton);

expect(env.component.errorState).toBe('paratext_tag_load_error');
expect(env.component.status).toBe('paratext_tag_load_error');
expect(env.getParatextTagOptions(env.component).length).toBe(0);
}));
expect(env.component.errorState).toBe('paratext_tag_load_error');
expect(env.component.status).toBe('paratext_tag_load_error');
expect(env.getParatextTagOptions(env.component).length).toBe(0);
}));
});
});

class TestEnvironment {
Expand Down Expand Up @@ -678,11 +694,13 @@ class TestEnvironment {
) {
this.questions = options.transceleratorQuestions || this.questions;
this.errorOnFetchQuestions = !!options.errorOnFetchQuestions;

this.fixture = TestBed.createComponent(ChildViewContainerComponent);

if (options.offline === true) {
this.online$.next(false);
this.setOnline(false);
}

this.fixture = TestBed.createComponent(ChildViewContainerComponent);
if (options.editedQuestionIds) {
this.simulateTransceleratorQuestionsAlreadyExisting(options.editedQuestionIds || []);
}
Expand Down Expand Up @@ -834,6 +852,7 @@ class TestEnvironment {

setOnline(value: boolean): void {
this.online$.next(value);
this.testOnlineStatusService.setIsOnline(value);
tick();
this.fixture.detectChanges();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -534,7 +534,7 @@
"network_error_transcelerator": "Network error fetching Transcelerator questions. Retrying ({{ count }}).",
"next": "Next",
"no_questions_available": "There are no questions for the books in this project.",
"no_transcelerator_offline": "Importing from Transcelerator is not available offline.",
"no_import_offline": "Importing from {{ method }} is not available offline.",
"question_for_verse": "Question for verse {{ number }}",
"question": "Question",
"reference_from": "Reference from",
Expand Down
Loading