-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(www): add initial draft of a new contact view (#1710)
* Add new contact us view. * Rough first draft of the new contact flow. * Add new contact us view to the app based on conditional `enableNewContactView` property. * Remove use of localize for the time being. We'll localize in a distinct step later. * Add validity checks to form. * Update support links. * Update form field names. * Make some methods private and add some docstrings. * Add initial test of support form. * Add initial test of contact view. * Revert legacy feedback view ID rename. * Undo linting change in unrelated files. * Add Jasmine types. * Exclude specs from the build. * Address some nullability checks in the contact view test file. * Fix Electron builds. * Fix some TypeScript compiler errors. * Add more `ContactView` test cases. * Parameterize test. * Add more `SupportForm` test cases. * Add test cases for the client vs. manager variants. * Add controls for the `ContactView` storybook example to switch between client and manager variants. * Rename `hasOpenTicketSelection` to avoid the implication that it's a boolean field. * Use type-safe equality operators. * Prefer setting properties over attributes. * Use `render...()` prefix in methods returning `TemplateResult` objects. * Update styling with some comments. * Rename flag to make it clear it's ephemeral. * Add a "cancel" button that cancels the form instead of using the back button to clear the entire element. * Hide the issue selector on reset. * Add a `FormValues` object and link them to the form fields so we set values more declaratively. * Add test case for resetting the form. * Set correct `min-height`. * Add missing license headers. * Simplify cancel button test case setup. * Use guard clause instead of ternary operator for progress bar render method. * Hoist maximum input lengths to static variables. * Move submission and cancellation logic from the `SupportForm` up to the `ContactView` component. * Remove unused `issueType` property on `SupportForm`. * Pass form values into the `SupportForm` component. * Update tests. * Fix field names. * Add test case for setting `values` property. * Remove hidden OS and version fields. * Bring issue type values in line with existing feedback values. * Fix existing feedback page.
- Loading branch information
Showing
21 changed files
with
9,552 additions
and
192 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
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 |
---|---|---|
@@ -1,7 +1,6 @@ | ||
{ | ||
"extends": "../../tsconfig.json", | ||
"extends": "../www/tsconfig.json", | ||
"compilerOptions": { | ||
"outDir": "../../build/electron", | ||
"lib": ["es2022", "dom"] | ||
"outDir": "../../build/electron" | ||
} | ||
} |
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
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
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
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,21 @@ | ||
/** | ||
* Copyright 2023 The Outline Authors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
/** The app variant to use, which dictates the options available to the user. */ | ||
export enum AppType { | ||
CLIENT = 'client', | ||
MANAGER = 'manager', | ||
} |
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,133 @@ | ||
/** | ||
* Copyright 2023 The Outline Authors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
import {ContactView} from './index'; | ||
|
||
import {fixture, html, nextFrame} from '@open-wc/testing'; | ||
import {SupportForm} from './support_form'; | ||
|
||
describe('ContactView', () => { | ||
let el: ContactView; | ||
|
||
beforeEach(async () => { | ||
el = await fixture(html` <contact-view></contact-view> `); | ||
}); | ||
|
||
it('is defined', async () => { | ||
expect(el).toBeInstanceOf(ContactView); | ||
}); | ||
|
||
it('hides issue selector by default', async () => { | ||
const issueSelector = el.shadowRoot?.querySelector('mwc-select[label="Outline issue"]'); | ||
expect(issueSelector?.hasAttribute('hidden')).toBeTrue(); | ||
}); | ||
|
||
it('hides support form by default', async () => { | ||
const supportForm = el.shadowRoot?.querySelector('support-form'); | ||
expect(supportForm).toBeNull(); | ||
}); | ||
|
||
it('shows exit message if the user selects that they have an open ticket', async () => { | ||
const radioButton = el.shadowRoot!.querySelector('mwc-formfield[label="Yes"] mwc-radio')! as HTMLElement; | ||
radioButton.click(); | ||
await nextFrame(); | ||
|
||
const exitCard = el.shadowRoot!.querySelector('outline-card')!; | ||
expect(exitCard.textContent).toContain('experiencing high support volume'); | ||
}); | ||
|
||
it('shows issue selector if the user selects that they have no open tickets', async () => { | ||
const radioButton = el.shadowRoot!.querySelector('mwc-formfield[label="No"] mwc-radio')! as HTMLElement; | ||
radioButton.click(); | ||
await nextFrame(); | ||
|
||
const issueSelector = el.shadowRoot!.querySelector('mwc-select[label="Outline issue"]'); | ||
expect(issueSelector?.hasAttribute('hidden')).toBeFalse(); | ||
}); | ||
|
||
describe('when the user selects issue', () => { | ||
let issueSelector: HTMLElement; | ||
|
||
beforeEach(async () => { | ||
issueSelector = el.shadowRoot!.querySelector('mwc-select[label="Outline issue"]')!; | ||
const radioButton: HTMLElement = el.shadowRoot!.querySelector('mwc-formfield[label="No"] mwc-radio')!; | ||
radioButton.click(); | ||
await nextFrame(); | ||
}); | ||
|
||
const conditions = [ | ||
{ | ||
testcaseName: 'I need an access key', | ||
value: 'no-server', | ||
expectedMsg: 'does not distribute free or paid access keys', | ||
}, | ||
{ | ||
testcaseName: 'I am having trouble adding a server using my access key', | ||
value: 'cannot-add-server', | ||
expectedMsg: 'assist with adding a server', | ||
}, | ||
{ | ||
testcaseName: 'I am having trouble connecting to my Outline VPN server', | ||
value: 'connection', | ||
expectedMsg: 'assist with connecting to a server', | ||
}, | ||
]; | ||
|
||
for (const {testcaseName, value, expectedMsg} of conditions) { | ||
it(`'${testcaseName}' shows exit message`, async () => { | ||
const issue: HTMLElement = issueSelector.querySelector(`mwc-list-item[value="${value}"]`)!; | ||
issue.click(); | ||
await nextFrame(); | ||
|
||
const exitCard = el.shadowRoot!.querySelector('outline-card')!; | ||
expect(exitCard.textContent).toContain(expectedMsg); | ||
}); | ||
} | ||
|
||
describe('"General feedback & suggestions"', () => { | ||
beforeEach(async () => { | ||
const issue: HTMLElement = issueSelector.querySelector('mwc-list-item[value="general"]')!; | ||
issue.click(); | ||
await nextFrame(); | ||
}); | ||
|
||
it('shows support form', async () => { | ||
const supportForm = el.shadowRoot!.querySelector('support-form')!; | ||
expect(supportForm).not.toBeNull(); | ||
}); | ||
|
||
it('shows "thank you" exit message on completion of support form', async () => { | ||
const supportForm: SupportForm = el.shadowRoot!.querySelector('support-form')!; | ||
supportForm.valid = true; | ||
supportForm.dispatchEvent(new CustomEvent('submit')); | ||
|
||
await nextFrame(); | ||
|
||
const exitCard = el.shadowRoot!.querySelector('outline-card')!; | ||
expect(exitCard.textContent).toContain('Thanks for helping us improve'); | ||
}); | ||
|
||
it('shows default contact view on cancellation of support form', async () => { | ||
el.shadowRoot!.querySelector('support-form')!.dispatchEvent(new CustomEvent('cancel')); | ||
|
||
await nextFrame(); | ||
|
||
expect(el.shadowRoot?.querySelector('p')?.textContent).toContain('Tell us how we can help.'); | ||
expect(el.shadowRoot?.querySelector('support-form')).toBeNull(); | ||
}); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.