-
Notifications
You must be signed in to change notification settings - Fork 70
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore(GetInTouch): Modularize contact URL management using GetInTouch…
…With class (#13139) chore(GetInTouch): Modularize contact URL management using GetInTouchWith class
- Loading branch information
1 parent
a16615c
commit 3016b0c
Showing
19 changed files
with
267 additions
and
58 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
25 changes: 25 additions & 0 deletions
25
frontend/packages/shared/src/getInTouch/GetInTouchWith.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { GetInTouchWith } from 'app-shared/getInTouch/GetInTouchWith'; | ||
import { | ||
EmailContactProvider, | ||
GitHubIssueContactProvider, | ||
SlackContactProvider, | ||
} from 'app-shared/getInTouch/providers'; | ||
|
||
describe('GetInTouchWith', () => { | ||
it('should be high-level module that support low-level module', () => { | ||
const contact = new GetInTouchWith(new EmailContactProvider()); | ||
expect(contact.url('serviceOwner')).toBe('mailto:tjenesteeier@altinn.no'); | ||
}); | ||
|
||
it('should have the same API regardless of used low-level implementation module', () => { | ||
const contactByEmail = new GetInTouchWith(new EmailContactProvider()); | ||
const contactBySlack = new GetInTouchWith(new SlackContactProvider()); | ||
const contactByGitHubIssue = new GetInTouchWith(new GitHubIssueContactProvider()); | ||
|
||
expect(contactByEmail.url('serviceDesk')).toBe('mailto:servicedesk@altinn.no'); | ||
expect(contactBySlack.url('altinn')).toBe('https://altinn.slack.com'); | ||
expect(contactByGitHubIssue.url('bugReport')).toBe( | ||
'https://github.com/Altinn/altinn-studio/issues/new?labels=kind/bug,status/triage&template=bug_report.yml', | ||
); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import { type GetInTouchProvider } from './interfaces/GetInTouchProvider'; | ||
|
||
export class GetInTouchWith<T, Options> { | ||
constructor(private contactProvider: GetInTouchProvider<T, Options>) {} | ||
|
||
public url(selectedChannel: T, options?: Options): string { | ||
return this.contactProvider.buildContactUrl(selectedChannel, options); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { GetInTouchWith } from './GetInTouchWith'; |
5 changes: 5 additions & 0 deletions
5
frontend/packages/shared/src/getInTouch/interfaces/GetInTouchProvider.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
export type Options<K extends string, V = string> = Partial<Record<K, V>>; | ||
|
||
export interface GetInTouchProvider<T, Options = null> { | ||
buildContactUrl: (channel: T, options?: Options) => string; | ||
} |
14 changes: 14 additions & 0 deletions
14
frontend/packages/shared/src/getInTouch/providers/EmailContactProvider.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import { EmailContactProvider } from 'app-shared/getInTouch/providers/EmailContactProvider'; | ||
|
||
describe('EmailContactProvider', () => { | ||
it('should return correct email based on selectedChannel', () => { | ||
const emailContactProvider = new EmailContactProvider(); | ||
|
||
expect(emailContactProvider.buildContactUrl('serviceOwner')).toBe( | ||
'mailto:tjenesteeier@altinn.no', | ||
); | ||
expect(emailContactProvider.buildContactUrl('serviceDesk')).toBe( | ||
'mailto:servicedesk@altinn.no', | ||
); | ||
}); | ||
}); |
14 changes: 14 additions & 0 deletions
14
frontend/packages/shared/src/getInTouch/providers/EmailContactProvider.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import { type GetInTouchProvider } from '../interfaces/GetInTouchProvider'; | ||
|
||
type EmailChannel = 'serviceDesk' | 'serviceOwner'; | ||
|
||
const emailChannelMap: Record<EmailChannel, string> = { | ||
serviceDesk: 'mailto:servicedesk@altinn.no', | ||
serviceOwner: 'mailto:tjenesteeier@altinn.no', | ||
}; | ||
|
||
export class EmailContactProvider implements GetInTouchProvider<EmailChannel> { | ||
public buildContactUrl(selectedChannel: EmailChannel): string { | ||
return emailChannelMap[selectedChannel]; | ||
} | ||
} |
57 changes: 57 additions & 0 deletions
57
frontend/packages/shared/src/getInTouch/providers/GitHubIssueContactProvider.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
import { type GetInTouchProvider, type Options } from '../interfaces/GetInTouchProvider'; | ||
|
||
type BugReportFields = 'title' | 'steps-to-reproduce' | 'additional-information'; | ||
type FeatureRequestFields = 'title' | 'description' | 'additional-information'; | ||
|
||
type GitHubIssueContactOptions = Options<BugReportFields | FeatureRequestFields, string>; | ||
|
||
type GitHubIssueTypes = 'featureRequest' | 'bugReport' | 'choose'; | ||
type MappableGithubTypes = Exclude<GitHubIssueTypes, 'choose'>; | ||
|
||
type GitHubChannelConfig = { | ||
labels: Array<string>; | ||
template: string; | ||
}; | ||
|
||
const gitHubIssueType: Record<MappableGithubTypes, GitHubChannelConfig> = { | ||
featureRequest: { | ||
labels: ['kind/feature-request', 'status/triage'], | ||
template: 'feature_request.yml', | ||
}, | ||
bugReport: { | ||
labels: ['kind/bug', 'status/triage'], | ||
template: 'bug_report.yml', | ||
}, | ||
}; | ||
|
||
export class GitHubIssueContactProvider | ||
implements GetInTouchProvider<GitHubIssueTypes, GitHubIssueContactOptions> | ||
{ | ||
private readonly githubRepoUrl: string = 'https://github.com/Altinn/altinn-studio'; | ||
private readonly githubIssueUrl: string = `${this.githubRepoUrl}/issues/new`; | ||
|
||
public buildContactUrl( | ||
selectedIssueType: GitHubIssueTypes, | ||
options?: GitHubIssueContactOptions, | ||
): string { | ||
if (selectedIssueType === 'choose') return `${this.githubIssueUrl}/${selectedIssueType}`; | ||
return ( | ||
this.githubIssueUrl + this.optionToUrlParams(gitHubIssueType[selectedIssueType], options) | ||
); | ||
} | ||
|
||
private optionToUrlParams( | ||
selectedConfig: GitHubChannelConfig, | ||
options?: GitHubIssueContactOptions, | ||
): string { | ||
const labels = selectedConfig.labels.join(','); | ||
const optionsQueryParams = options ? `&${this.mapOptionsToQueryParams(options)}` : ''; | ||
return `?labels=${labels}&template=${selectedConfig.template}${optionsQueryParams}`; | ||
} | ||
|
||
private mapOptionsToQueryParams(options: GitHubIssueContactOptions): string { | ||
return Object.entries(options) | ||
.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`) | ||
.join('&'); | ||
} | ||
} |
30 changes: 30 additions & 0 deletions
30
frontend/packages/shared/src/getInTouch/providers/GitHubIssuesContactProvider.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import { GitHubIssueContactProvider } from 'app-shared/getInTouch/providers/GitHubIssueContactProvider'; | ||
|
||
describe('GitHubIssuesContactProvider', () => { | ||
it('should return correct link based on selected issue type', () => { | ||
const gitHubIssuesContactProvider = new GitHubIssueContactProvider(); | ||
expect(gitHubIssuesContactProvider.buildContactUrl('featureRequest')).toBe( | ||
'https://github.com/Altinn/altinn-studio/issues/new?labels=kind/feature-request,status/triage&template=feature_request.yml', | ||
); | ||
|
||
expect(gitHubIssuesContactProvider.buildContactUrl('bugReport')).toBe( | ||
'https://github.com/Altinn/altinn-studio/issues/new?labels=kind/bug,status/triage&template=bug_report.yml', | ||
); | ||
|
||
expect(gitHubIssuesContactProvider.buildContactUrl('choose')).toBe( | ||
'https://github.com/Altinn/altinn-studio/issues/new/choose', | ||
); | ||
}); | ||
|
||
it('should support options to prefill form', () => { | ||
const gitHubIssuesContactProvider = new GitHubIssueContactProvider(); | ||
expect( | ||
gitHubIssuesContactProvider.buildContactUrl('bugReport', { | ||
title: 'title of the issue', | ||
'additional-information': 'cannot read property of undefined, reading id', | ||
}), | ||
).toBe( | ||
'https://github.com/Altinn/altinn-studio/issues/new?labels=kind/bug,status/triage&template=bug_report.yml&title=title%20of%20the%20issue&additional-information=cannot%20read%20property%20of%20undefined%2C%20reading%20id', | ||
); | ||
}); | ||
}); |
12 changes: 12 additions & 0 deletions
12
frontend/packages/shared/src/getInTouch/providers/SlackContactProvider.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { SlackContactProvider } from 'app-shared/getInTouch/providers/SlackContactProvider'; | ||
|
||
describe('SlackContactProvider', () => { | ||
it('should return correct Slack link based on selectedChannel', () => { | ||
const slackContactProvider = new SlackContactProvider(); | ||
|
||
expect(slackContactProvider.buildContactUrl('altinn')).toBe('https://altinn.slack.com'); | ||
expect(slackContactProvider.buildContactUrl('product-altinn-studio')).toBe( | ||
'https://altinn.slack.com/archives/C02EJ9HKQA3', | ||
); | ||
}); | ||
}); |
14 changes: 14 additions & 0 deletions
14
frontend/packages/shared/src/getInTouch/providers/SlackContactProvider.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import { type GetInTouchProvider } from '../interfaces/GetInTouchProvider'; | ||
|
||
type SlackChannel = 'product-altinn-studio' | 'altinn'; | ||
|
||
const slackChannelMap: Record<SlackChannel, string> = { | ||
'product-altinn-studio': 'https://altinn.slack.com/archives/C02EJ9HKQA3', | ||
altinn: 'https://altinn.slack.com', | ||
}; | ||
|
||
export class SlackContactProvider implements GetInTouchProvider<SlackChannel> { | ||
public buildContactUrl(selectedChannel: SlackChannel): string { | ||
return slackChannelMap[selectedChannel]; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export { EmailContactProvider } from './EmailContactProvider'; | ||
export { GitHubIssueContactProvider } from './GitHubIssueContactProvider'; | ||
export { SlackContactProvider } from './SlackContactProvider'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import React from 'react'; | ||
import { screen, render } from '@testing-library/react'; | ||
import { textMock } from '@studio/testing/mocks/i18nMock'; | ||
import { ContactPage } from './ContactPage'; | ||
|
||
describe('ContactPage', () => { | ||
it('should display the main heading', () => { | ||
render(<ContactPage />); | ||
expect( | ||
screen.getByRole('heading', { name: textMock('general.contact'), level: 1 }), | ||
).toBeInTheDocument(); | ||
}); | ||
|
||
it('should display the contact by email section with its content and link', () => { | ||
render(<ContactPage />); | ||
expect( | ||
screen.getByRole('heading', { name: textMock('contact.email.heading') }), | ||
).toBeInTheDocument(); | ||
expect(screen.getByText(textMock('contact.email.content'))).toBeInTheDocument(); | ||
expect( | ||
screen.getByRole('link', { name: textMock('general.service_desk.email') }), | ||
).toBeInTheDocument(); | ||
}); | ||
|
||
it('should display the contact by Slack section with its content, list, and link', () => { | ||
render(<ContactPage />); | ||
|
||
expect( | ||
screen.getByRole('heading', { name: textMock('contact.slack.heading') }), | ||
).toBeInTheDocument(); | ||
expect(screen.getByText(textMock('contact.slack.content'))).toBeInTheDocument(); | ||
expect(screen.getByText(textMock('contact.slack.content_list'))).toBeInTheDocument(); | ||
expect(screen.getByRole('link', { name: textMock('contact.slack.link') })).toBeInTheDocument(); | ||
}); | ||
|
||
it('should display the bug report and feature request section with its content and link', () => { | ||
render(<ContactPage />); | ||
|
||
expect( | ||
screen.getByRole('heading', { name: textMock('contact.github_issue.heading') }), | ||
).toBeInTheDocument(); | ||
expect(screen.getByText(textMock('contact.github_issue.content'))).toBeInTheDocument(); | ||
expect( | ||
screen.getByRole('link', { name: textMock('contact.github_issue.link_label') }), | ||
).toBeInTheDocument(); | ||
}); | ||
}); |
Oops, something went wrong.