Skip to content
Open
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 @@ -9,13 +9,15 @@ export default function useGiveLinks() {
}

function getLinks(search: string) {
if (search.includes('Instructor')) {
const keys = Array.from(new URLSearchParams(search).keys()).map((k) => k.toLowerCase());

if (keys.includes('instructor resources')) {
return [
'https://riceconnect.rice.edu/donation/support-openstax-instructor-resources',
'https://riceconnect.rice.edu/donation/support-openstax-instructor-resources-b'
];
}
if (search.includes('Student')) {
if (keys.includes('student resources')) {
return [
'https://riceconnect.rice.edu/donation/support-openstax-student-resources',
'https://riceconnect.rice.edu/donation/support-openstax-student-resources-b'
Expand Down
5 changes: 3 additions & 2 deletions src/app/pages/details/common/resource-box/left-content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,12 @@ const iconLookup: {[key: string]: IconDefinition} = {
// string says nothing about the resource there.
function useVariant(): VariantValue {
const {search} = useLocation();
const keys = Array.from(new URLSearchParams(search).keys()).map((k) => k.toLowerCase());

if (search.includes('Instructor')) {
if (keys.includes('instructor resources')) {
return 'Instructor resource';
}
if (search.includes('Student')) {
if (keys.includes('student resources')) {
return 'Student resource';
}
return '? resource';
Expand Down
18 changes: 12 additions & 6 deletions src/app/pages/details/common/tab-utils.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
export function findSelectedTab(labels: string[]) {
const possibleTabs = Array.from(new window.URLSearchParams(window.location.search).keys());

return labels.find((label) => possibleTabs.includes(label)) || labels[0];
return (
labels.find((label) =>
possibleTabs.some((tab) => tab.toLowerCase() === label.toLowerCase())
) || labels[0]
);
}

export function replaceSearchTerm(labels: string[], newValue: string) {
const lowerLabels = labels.map((label) => label.toLowerCase());
const possibleTabs = Array.from(new window.URLSearchParams(window.location.search).keys());
const index = possibleTabs.findIndex((t) => labels.includes(t));
const firstIndex = possibleTabs.findIndex((tab) => lowerLabels.includes(tab.toLowerCase()));
const filtered = possibleTabs.filter((tab) => !lowerLabels.includes(tab.toLowerCase()));

if (index < 0) {
possibleTabs.unshift(encodeURIComponent(newValue));
if (firstIndex < 0) {
filtered.unshift(newValue);
} else {
possibleTabs[index] = encodeURIComponent(newValue);
filtered.splice(firstIndex, 0, newValue);
}
return `?${possibleTabs.join('&')}`;
return `?${filtered.map((tab) => encodeURIComponent(tab)).join('&')}`;
}
42 changes: 36 additions & 6 deletions test/src/pages/details/common/tab-utils.test.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,47 @@
import { replaceSearchTerm } from '~/pages/details/common/tab-utils';
import {findSelectedTab, replaceSearchTerm} from '~/pages/details/common/tab-utils';

function setSearch(search: string) {
Reflect.defineProperty(window, 'location', {
writable: true,
value: { search }
});
}

describe('tab-utils', () => {
const labels = ['one', 'two'];
const newValue = 'three';

it('adds new param if no tabs in search params', () => {
setSearch('');
expect(replaceSearchTerm(labels, newValue)).toBe('?three');
});
it('replaces param if tab is in search params', () => {
Reflect.defineProperty(window, 'location', {
writable: true,
value: { search: '?fluff&two' }
});
expect(replaceSearchTerm(labels, newValue)).toBe('?fluff&three');
setSearch('?fluff&two');
expect(replaceSearchTerm(labels, newValue)).toBe('?fluff&three');
});
it('replaces param when the key case does not match a label', () => {
setSearch('?TWO');
expect(replaceSearchTerm(labels, newValue)).toBe('?three');
});

describe('findSelectedTab', () => {
const tabLabels = ['Book details', 'Instructor resources', 'Student resources'];

it('selects the matching tab', () => {
setSearch('?Instructor%20resources');
expect(findSelectedTab(tabLabels)).toBe('Instructor resources');
});
it('matches a lower-case deep link', () => {
setSearch('?instructor%20resources');
expect(findSelectedTab(tabLabels)).toBe('Instructor resources');
});
it('falls back to the first label when no key matches', () => {
setSearch('?nothing');
expect(findSelectedTab(tabLabels)).toBe('Book details');
});
it('replaces a lower-case key instead of keeping it', () => {
setSearch('?instructor%20resources');
expect(replaceSearchTerm(tabLabels, 'Student resources')).toBe('?Student%20resources');
});
});
});
18 changes: 12 additions & 6 deletions test/src/pages/details/left-content.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ describe('left-content', () => {
});
const model = {link, ...baseModel, ...{iconType: 'unlock'}};

render(<Component model={model} search="Student" />);
render(<Component model={model} search="STUDENT%20RESOURCES" />);
const foundLink = screen.getByRole('link');

expect(foundLink.textContent).toBe('button-label');
Expand All @@ -93,14 +93,16 @@ describe('left-content', () => {
});
const model = {link, ...baseModel, iconType: 'download'};

render(<Component model={model} />);
render(<Component model={model} search="instructor%20resources" />);
const foundLink = screen.getByRole('link');

expect(foundLink.textContent).toBe('button-label');
await user.click(foundLink);
await screen.findByText('Give today');
const giveToday = await screen.findByText('Give today');
const downloadLink = await screen.findByText('Go to your resource');

expect(giveToday.closest('a')?.getAttribute('href')).toContain('support-openstax-instructor-resources');
expect(document.querySelector('[data-nudge-placement="Instructor resource"]')).toBeTruthy();
await user.click(downloadLink);
});
it('tracks a download for a signed-in non-instructor', async () => {
Expand All @@ -113,14 +115,16 @@ describe('left-content', () => {
});
const model = {link, ...baseModel, iconType: 'download'};

render(<Component model={model} search="Student" />);
render(<Component model={model} search="STUDENT%20RESOURCES" />);
const foundLink = screen.getByRole('link');

expect(foundLink.textContent).toBe('button-label');
await user.click(foundLink);
await screen.findByText('Give today');
const giveToday = await screen.findByText('Give today');
const downloadLink = await screen.findByText('Go to your resource');

expect(giveToday.closest('a')?.getAttribute('href')).toContain('support-openstax-student-resources');
expect(document.querySelector('[data-nudge-placement="Student resource"]')).toBeTruthy();
await user.click(downloadLink);

expect(trackLink).toHaveBeenCalledWith(expect.anything(), '1');
Expand Down Expand Up @@ -159,9 +163,11 @@ describe('left-content', () => {

expect(foundLink.textContent).toBe('button-label');
await user.click(foundLink);
await screen.findByText('Give today');
const giveToday = await screen.findByText('Give today');
const downloadLink = await screen.findByText('Go to your resource');

expect(giveToday.closest('a')?.getAttribute('href')).toContain('support-openstax-subject');
expect(document.querySelector('[data-nudge-placement="? resource"]')).toBeTruthy();
await user.click(downloadLink);
});
it('handles unknown icon and unknown search', async () => {
Expand Down
Loading