| /** |
| * @license |
| * Copyright 2022 Google LLC |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| import * as sinon from 'sinon'; |
| import {assert} from '@open-wc/testing'; |
| import {SinonStubbedMember} from 'sinon'; |
| import { |
| AccountId, |
| BranchName, |
| EmailAddress, |
| NumericChangeId, |
| RepoName, |
| TopicName, |
| } from '../../api/rest-api'; |
| import { |
| NavigationService, |
| navigationToken, |
| } from '../../elements/core/gr-navigation/gr-navigation'; |
| import '../../test/common-test-setup'; |
| import {testResolver} from '../../test/common-test-setup'; |
| import {createChange} from '../../test/test-data-generators'; |
| import { |
| createSearchUrl, |
| SearchUrlOptions, |
| SearchViewModel, |
| searchViewModelToken, |
| } from './search'; |
| |
| const CHANGE_ID = 'IcA3dAB3edAB9f60B8dcdA6ef71A75980e4B7127'; |
| const COMMIT_HASH = '12345678'; |
| |
| suite('search view state tests', () => { |
| test('createSearchUrl', () => { |
| let options: SearchUrlOptions = { |
| owner: 'a%b', |
| repo: 'c%d' as RepoName, |
| branch: 'e%f' as BranchName, |
| topic: 'g%h' as TopicName, |
| statuses: ['op%en'], |
| }; |
| assert.equal( |
| createSearchUrl(options), |
| '/q/owner:a%2525b+project:c%2525d+branch:e%2525f+' + |
| 'topic:"g%2525h"+status:op%2525en' |
| ); |
| |
| window.CANONICAL_PATH = '/base'; |
| assert.equal(createSearchUrl(options).substring(0, 5), '/base'); |
| window.CANONICAL_PATH = undefined; |
| |
| options.offset = 100; |
| assert.equal( |
| createSearchUrl(options), |
| '/q/owner:a%2525b+project:c%2525d+branch:e%2525f+' + |
| 'topic:"g%2525h"+status:op%2525en,100' |
| ); |
| delete options.offset; |
| |
| // The presence of the query param overrides other options. |
| options.query = 'foo$bar'; |
| assert.equal(createSearchUrl(options), '/q/foo%24bar'); |
| |
| options.offset = 100; |
| assert.equal(createSearchUrl(options), '/q/foo%24bar,100'); |
| |
| options = {statuses: ['a', 'b', 'c']}; |
| assert.equal( |
| createSearchUrl(options), |
| '/q/(status:a OR status:b OR status:c)' |
| ); |
| |
| options = {topic: 'test' as TopicName}; |
| assert.equal(createSearchUrl(options), '/q/topic:"test"'); |
| |
| options = {topic: 'test test' as TopicName}; |
| assert.equal(createSearchUrl(options), '/q/topic:"test+test"'); |
| |
| options = {topic: 'test:test' as TopicName}; |
| assert.equal(createSearchUrl(options), '/q/topic:"test:test"'); |
| }); |
| |
| suite('query based navigation', () => { |
| let replaceUrlStub: SinonStubbedMember<NavigationService['replaceUrl']>; |
| let model: SearchViewModel; |
| |
| setup(() => { |
| model = testResolver(searchViewModelToken); |
| replaceUrlStub = sinon.stub(testResolver(navigationToken), 'replaceUrl'); |
| }); |
| |
| teardown(() => { |
| model.finalize(); |
| }); |
| |
| test('Searching for a change ID redirects to change', async () => { |
| const change = {...createChange(), _number: 1 as NumericChangeId}; |
| |
| model.redirectSingleResult(CHANGE_ID, [change]); |
| |
| assert.isTrue(replaceUrlStub.called); |
| assert.equal(replaceUrlStub.lastCall.firstArg, '/c/test-project/+/1'); |
| }); |
| |
| test('Searching for a change num redirects to change', async () => { |
| const change = {...createChange(), _number: 1 as NumericChangeId}; |
| |
| model.redirectSingleResult('1', [change]); |
| |
| assert.isTrue(replaceUrlStub.called); |
| assert.equal(replaceUrlStub.lastCall.firstArg, '/c/test-project/+/1'); |
| }); |
| |
| test('Commit hash redirects to change', async () => { |
| const change = {...createChange(), _number: 1 as NumericChangeId}; |
| |
| model.redirectSingleResult(COMMIT_HASH, [change]); |
| |
| assert.isTrue(replaceUrlStub.called); |
| assert.equal(replaceUrlStub.lastCall.firstArg, '/c/test-project/+/1'); |
| }); |
| |
| test('No results: no redirect', async () => { |
| model.redirectSingleResult(CHANGE_ID, []); |
| |
| assert.isFalse(replaceUrlStub.called); |
| }); |
| |
| test('More than 1 result: no redirect', async () => { |
| const change1 = {...createChange(), _number: 1 as NumericChangeId}; |
| const change2 = {...createChange(), _number: 2 as NumericChangeId}; |
| |
| model.redirectSingleResult(CHANGE_ID, [change1, change2]); |
| |
| assert.isFalse(replaceUrlStub.called); |
| }); |
| }); |
| |
| suite('selectors', () => { |
| let model: SearchViewModel; |
| let userId: AccountId | EmailAddress | undefined; |
| let repo: RepoName | undefined; |
| |
| setup(() => { |
| model = testResolver(searchViewModelToken); |
| model.userId$.subscribe(x => (userId = x)); |
| model.repo$.subscribe(x => (repo = x)); |
| }); |
| |
| teardown(() => { |
| model.finalize(); |
| }); |
| |
| test('userId', async () => { |
| assert.isUndefined(userId); |
| |
| // userId set when all owners are the same |
| model.updateState({ |
| query: 'owner:foo', |
| changes: [ |
| {...createChange(), owner: {email: 'foo@bar' as EmailAddress}}, |
| {...createChange(), owner: {email: 'foo@bar' as EmailAddress}}, |
| ], |
| }); |
| assert.equal(userId, 'foo@bar' as EmailAddress); |
| |
| // userId not set when multiple owners exist |
| model.updateState({ |
| query: 'owner:foo', |
| changes: [ |
| {...createChange(), owner: {email: 'foo@bar' as EmailAddress}}, |
| {...createChange(), owner: {email: 'foo@foo' as EmailAddress}}, |
| ], |
| }); |
| assert.isUndefined(userId); |
| |
| // userId not set when query is not about owner |
| model.updateState({ |
| query: 'foo bar baz', |
| changes: [ |
| {...createChange(), owner: {email: 'foo@bar' as EmailAddress}}, |
| ], |
| }); |
| assert.isUndefined(userId); |
| }); |
| |
| test('repo', async () => { |
| assert.isUndefined(repo); |
| |
| model.updateState({ |
| query: 'foo bar baz', |
| changes: [{...createChange(), project: 'test-repo' as RepoName}], |
| }); |
| assert.isUndefined(repo); |
| |
| model.updateState({ |
| query: 'foo bar baz', |
| changes: [{...createChange()}], |
| }); |
| assert.isUndefined(repo); |
| |
| model.updateState({ |
| query: 'project: test-repo', |
| changes: [{...createChange(), project: 'test-repo' as RepoName}], |
| }); |
| assert.equal(repo, 'test-repo' as RepoName); |
| |
| model.updateState({ |
| query: 'project:test-repo status:open', |
| changes: [{...createChange(), project: 'test-repo' as RepoName}], |
| }); |
| assert.equal(repo, 'test-repo' as RepoName); |
| }); |
| }); |
| }); |