| /** |
| * @license |
| * Copyright 2021 Google LLC |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| import '../../test/common-test-setup'; |
| import { |
| createAccountWithEmail, |
| createChangeViewState, |
| createDraft, |
| } from '../../test/test-data-generators'; |
| import { |
| AccountInfo, |
| CommentInfo, |
| EmailAddress, |
| NumericChangeId, |
| Timestamp, |
| UrlEncodedCommentId, |
| } from '../../types/common'; |
| import {CommentsModel, deleteDraft} from './comments-model'; |
| import {Subscription} from 'rxjs'; |
| import { |
| createComment, |
| createParsedChange, |
| } from '../../test/test-data-generators'; |
| import {stubRestApi, waitUntil, waitUntilCalled} from '../../test/test-utils'; |
| import {getAppContext} from '../../services/app-context'; |
| import {changeModelToken} from '../change/change-model'; |
| import {assert} from '@open-wc/testing'; |
| import {testResolver} from '../../test/common-test-setup'; |
| import {accountsModelToken} from '../accounts-model/accounts-model'; |
| import {ChangeComments} from '../../elements/diff/gr-comment-api/gr-comment-api'; |
| import {changeViewModelToken} from '../views/change'; |
| import {navigationToken} from '../../elements/core/gr-navigation/gr-navigation'; |
| |
| suite('comments model tests', () => { |
| test('updateStateDeleteDraft', () => { |
| const draft = createDraft(); |
| draft.id = '1' as UrlEncodedCommentId; |
| const state = { |
| comments: {}, |
| robotComments: {}, |
| drafts: { |
| [draft.path!]: [draft], |
| }, |
| portedComments: {}, |
| portedDrafts: {}, |
| discardedDrafts: [], |
| }; |
| const output = deleteDraft(state, draft); |
| assert.deepEqual(output, { |
| comments: {}, |
| robotComments: {}, |
| drafts: { |
| 'abc.txt': [], |
| }, |
| portedComments: {}, |
| portedDrafts: {}, |
| discardedDrafts: [{...draft}], |
| }); |
| }); |
| }); |
| |
| suite('change service tests', () => { |
| let subscriptions: Subscription[] = []; |
| |
| teardown(() => { |
| for (const s of subscriptions) { |
| s.unsubscribe(); |
| } |
| subscriptions = []; |
| }); |
| |
| test('loads comments', async () => { |
| const model = new CommentsModel( |
| testResolver(changeViewModelToken), |
| testResolver(changeModelToken), |
| testResolver(accountsModelToken), |
| getAppContext().restApiService, |
| getAppContext().reportingService, |
| testResolver(navigationToken) |
| ); |
| const diffCommentsSpy = stubRestApi('getDiffComments').returns( |
| Promise.resolve({'foo.c': [createComment()]}) |
| ); |
| const diffRobotCommentsSpy = stubRestApi('getDiffRobotComments').returns( |
| Promise.resolve({}) |
| ); |
| const diffDraftsSpy = stubRestApi('getDiffDrafts').returns( |
| Promise.resolve({}) |
| ); |
| const portedCommentsSpy = stubRestApi('getPortedComments').returns( |
| Promise.resolve({'foo.c': [createComment()]}) |
| ); |
| const portedDraftsSpy = stubRestApi('getPortedDrafts').returns( |
| Promise.resolve({}) |
| ); |
| let comments: {[path: string]: CommentInfo[]} = {}; |
| subscriptions.push(model.comments$.subscribe(c => (comments = c ?? {}))); |
| let portedComments: {[path: string]: CommentInfo[]} = {}; |
| subscriptions.push( |
| model.portedComments$.subscribe(c => (portedComments = c ?? {})) |
| ); |
| |
| testResolver(changeViewModelToken).setState(createChangeViewState()); |
| testResolver(changeModelToken).updateStateChange(createParsedChange()); |
| |
| await waitUntilCalled(diffCommentsSpy, 'diffCommentsSpy'); |
| await waitUntilCalled(diffRobotCommentsSpy, 'diffRobotCommentsSpy'); |
| await waitUntilCalled(diffDraftsSpy, 'diffDraftsSpy'); |
| await waitUntilCalled(portedCommentsSpy, 'portedCommentsSpy'); |
| await waitUntilCalled(portedDraftsSpy, 'portedDraftsSpy'); |
| await waitUntil( |
| () => Object.keys(comments).length > 0, |
| 'comment in model not set' |
| ); |
| await waitUntil( |
| () => Object.keys(portedComments).length > 0, |
| 'ported comment in model not set' |
| ); |
| |
| assert.equal(comments['foo.c'].length, 1); |
| assert.equal(comments['foo.c'][0].id, '12345'); |
| assert.equal(portedComments['foo.c'].length, 1); |
| assert.equal(portedComments['foo.c'][0].id, '12345'); |
| }); |
| |
| test('duplicate mentions are filtered out', async () => { |
| const account = { |
| ...createAccountWithEmail('abcd@def.com' as EmailAddress), |
| registered_on: '2015-03-12 18:32:08.000000000' as Timestamp, |
| }; |
| stubRestApi('getAccountDetails').returns(Promise.resolve(account)); |
| const model = new CommentsModel( |
| testResolver(changeViewModelToken), |
| testResolver(changeModelToken), |
| testResolver(accountsModelToken), |
| getAppContext().restApiService, |
| getAppContext().reportingService, |
| testResolver(navigationToken) |
| ); |
| let mentionedUsers: AccountInfo[] = []; |
| const draft = {...createDraft(), message: 'hey @abc@def.com'}; |
| model.mentionedUsersInDrafts$.subscribe(x => (mentionedUsers = x)); |
| model.setState({ |
| drafts: { |
| 'abc.txt': [draft, draft], |
| }, |
| discardedDrafts: [], |
| }); |
| |
| await waitUntil(() => mentionedUsers.length > 0); |
| |
| assert.deepEqual(mentionedUsers, [account]); |
| }); |
| |
| test('empty mentions are emitted', async () => { |
| const account = { |
| ...createAccountWithEmail('abcd@def.com' as EmailAddress), |
| registered_on: '2015-03-12 18:32:08.000000000' as Timestamp, |
| }; |
| stubRestApi('getAccountDetails').returns(Promise.resolve(account)); |
| const model = new CommentsModel( |
| testResolver(changeViewModelToken), |
| testResolver(changeModelToken), |
| testResolver(accountsModelToken), |
| getAppContext().restApiService, |
| getAppContext().reportingService, |
| testResolver(navigationToken) |
| ); |
| let mentionedUsers: AccountInfo[] = []; |
| const draft = {...createDraft(), message: 'hey @abc@def.com'}; |
| model.mentionedUsersInDrafts$.subscribe(x => (mentionedUsers = x)); |
| model.setState({ |
| drafts: { |
| 'abc.txt': [draft], |
| }, |
| discardedDrafts: [], |
| }); |
| |
| await waitUntil(() => mentionedUsers.length > 0); |
| |
| assert.deepEqual(mentionedUsers, [account]); |
| |
| model.setState({ |
| drafts: { |
| 'abc.txt': [], |
| }, |
| discardedDrafts: [], |
| }); |
| await waitUntil(() => mentionedUsers.length === 0); |
| }); |
| |
| test('delete comment change is emitted', async () => { |
| const comment = createComment(); |
| stubRestApi('deleteComment').returns( |
| Promise.resolve({ |
| ...comment, |
| message: 'Comment is deleted', |
| }) |
| ); |
| const model = new CommentsModel( |
| testResolver(changeViewModelToken), |
| testResolver(changeModelToken), |
| testResolver(accountsModelToken), |
| getAppContext().restApiService, |
| getAppContext().reportingService, |
| testResolver(navigationToken) |
| ); |
| |
| let changeComments: ChangeComments | undefined = undefined; |
| model.changeComments$.subscribe(x => (changeComments = x)); |
| model.setState({ |
| comments: {[comment.path!]: [comment]}, |
| discardedDrafts: [], |
| }); |
| |
| model.deleteComment(123 as NumericChangeId, comment, 'Comment is deleted'); |
| |
| await waitUntil( |
| () => |
| changeComments?.getAllCommentsForPath(comment.path!)[0].message === |
| 'Comment is deleted' |
| ); |
| }); |
| }); |