Skip to content

Commit

Permalink
fix: issue with caching when selecting transport filter (#229)
Browse files Browse the repository at this point in the history
* chore: adds test case for filter

* chore: adds tests for non-transit

* chore: adds tests for boat and Correspondance

* fix: cache when transportmode is active
  • Loading branch information
mikaelbr authored Feb 16, 2024
1 parent f68b373 commit 6f89a59
Show file tree
Hide file tree
Showing 9 changed files with 189 additions and 37 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/playwright-scheduled-staging.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ jobs:
- name: Run Playwright tests
run: yarn playwright test
env:
NEXT_PUBLIC_PLANNER_ORG_ID: atb
NEXT_PUBLIC_PLANNER_ORG_ID: ${{ matrix.env }}
E2E_URL: 'https://${{ matrix.env }}-staging.planner-web.mittatb.no/'

- uses: actions/upload-artifact@v4
Expand Down
79 changes: 79 additions & 0 deletions e2e-tests/assistant-view.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { test, expect } from '@playwright/test';

test.use({
geolocation: { longitude: 62.4722, latitude: 6.1495 },
permissions: ['geolocation'],
});

test('Should fetch Kristiansund - Molde and loading more after first result', async ({
page,
}) => {
await page.goto(process.env.E2E_URL ?? 'http://localhost:3000');

await page.getByRole('textbox', { name: 'From' }).click();
await page.getByRole('textbox', { name: 'From' }).fill('Kristiansund');
await page
.getByRole('option', { name: 'Kristiansund Kristiansund', exact: true })
.click();

await page.getByRole('textbox', { name: 'To' }).click();
await page.getByRole('textbox', { name: 'To' }).fill('Molde');

const initialRequest = page.waitForResponse((request) => {
return request.url().includes('trip') && request.url().includes('cursor');
});

await page.getByRole('option', { name: 'Molde Molde', exact: true }).click();

await initialRequest;

await page.getByRole('button', { name: 'More choices' }).click();
await page.getByText('Bus', { exact: true }).click();
await page.getByRole('button', { name: 'Find departures' }).click();

const tripPatternItem = page.getByTestId('tripPattern-0-0');
await tripPatternItem.waitFor();

const additionalRequest = page.waitForRequest((request) => {
return request.url().includes('trip') && request.url().includes('cursor');
});
await page.getByRole('button', { name: 'Load more results' }).click();

await additionalRequest;
});

test('should show non transit trips on walkable distance', async ({ page }) => {
await page.goto(process.env.E2E_URL ?? 'http://localhost:3000');
await page.getByRole('textbox', { name: 'From' }).click();
await page.getByRole('textbox', { name: 'From' }).fill('Fylkeshuset i Møre');
await page
.getByRole('option', { name: 'Fylkeshuset i Møre og Romsdal' })
.click();
await page.getByRole('textbox', { name: 'To' }).click();
await page.getByRole('textbox', { name: 'To' }).fill('Roseby');
await page.getByRole('option', { name: 'Roseby Molde', exact: true }).click();

await page.getByTestId('non-transit-pill-foot').click();

await expect(
page.getByRole('heading', { name: 'Fylkeshuset i Møre og Romsdal' }),
).toBeVisible();
});

test('should show non transit trips on cyclable distance', async ({ page }) => {
await page.goto(process.env.E2E_URL ?? 'http://localhost:3000');
await page.getByRole('textbox', { name: 'From' }).click();
await page.getByRole('textbox', { name: 'From' }).fill('Fylkeshuset i Møre');
await page
.getByRole('option', { name: 'Fylkeshuset i Møre og Romsdal' })
.click();
await page.getByRole('textbox', { name: 'To' }).click();
await page.getByRole('textbox', { name: 'To' }).fill('Roseby');
await page.getByRole('option', { name: 'Roseby Molde', exact: true }).click();

await page.getByTestId('non-transit-pill-bicycle').click();

await expect(
page.getByRole('heading', { name: 'Fylkeshuset i Møre og Romsdal' }),
).toBeVisible();
});
88 changes: 88 additions & 0 deletions e2e-tests/fram-specific/assistant.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { test, expect } from '@playwright/test';

test.use({
geolocation: { longitude: 62.4722, latitude: 6.1495 },
permissions: ['geolocation'],
});

test.describe('fram only', () => {
test.skip(
() => process.env.NEXT_PUBLIC_PLANNER_ORG_ID !== 'fram',
'Only FRAM!',
);

test('Should filter on line 701', async ({ page }) => {
await page.goto(process.env.E2E_URL ?? 'http://localhost:3000');

await page.getByRole('textbox', { name: 'From' }).click();
await page.getByRole('textbox', { name: 'From' }).fill('Kvam');
await page.getByRole('option', { name: 'Kvam skole Molde' }).click();

await page.getByRole('textbox', { name: 'To' }).click();
await page.getByRole('textbox', { name: 'To' }).fill('Fylkeshusa');

const tripResponse = page.waitForResponse((request) => {
return request.url().includes('assistant/trip');
});
await page.getByRole('option', { name: 'Fylkeshusa Molde' }).click();

await page.getByRole('button', { name: 'More choices' }).click();

await tripResponse;

await page.getByPlaceholder('line number').click();
await page.getByPlaceholder('line number').fill('701');

const tripResponse2 = page.waitForResponse((request) => {
return request.url().includes('assistant/trip');
});
await page.getByRole('button', { name: 'Find departures' }).click();
await tripResponse2;

const tripPatternItem2 = page.getByTestId('tripPattern-0-0');
await tripPatternItem2.waitFor();

await expect(tripPatternItem2).toBeVisible();
expect(await tripPatternItem2.getAttribute('aria-label')).toContain('701');
});

test('should show boats and message on Correspondance', async ({ page }) => {
await page.goto(process.env.E2E_URL ?? 'http://localhost:3000');

await page.getByRole('textbox', { name: 'From' }).click();
await page.getByRole('textbox', { name: 'From' }).fill('Moa trafikktermin');
await page.getByRole('option', { name: 'Moa trafikkterminal' }).click();

await page.getByRole('textbox', { name: 'To' }).click();
await page.getByRole('textbox', { name: 'To' }).fill('Ulsteinvik');

const additionalRequest = page.waitForResponse((request) => {
return request.url().includes('trip');
});

await page
.getByRole('option', { name: 'Ulsteinvik Ulstein', exact: true })
.click();

await additionalRequest;

await page.getByTestId('tripPattern-0-0').waitFor();

await page.getByRole('button', { name: 'More choices' }).click();

const additionalRequest2 = page.waitForResponse((request) => {
return (
request.url().includes('trip') && request.url().includes('expressboat')
);
});
await page.locator('label').filter({ hasText: 'Express boat' }).click();
await page.getByText('Bus', { exact: true }).click();

await page.getByText('Loading travel suggestions...').waitFor();

await additionalRequest2;

await page.getByText('1145').first().click();
await expect(page.getByText('Correspondance between 1145')).toBeVisible();
});
});
29 changes: 0 additions & 29 deletions e2e-tests/search-test.spec.ts

This file was deleted.

2 changes: 2 additions & 0 deletions src/page-modules/assistant/__tests__/assistant.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,7 @@ describe('assistant page', function () {
transportModeFilter: null,
cursor: null,
lineFilter: null,
via: null,
};
const fromToTripQuery2: FromToTripQuery = {
from: fromFeature,
Expand Down Expand Up @@ -286,6 +287,7 @@ describe('assistant page', function () {
transportModeFilter: null,
cursor: null,
lineFilter: null,
via: null,
};

addAssistantTripToCache(cachedFromToTripQuery, tripResult);
Expand Down
1 change: 1 addition & 0 deletions src/page-modules/assistant/non-transit-pill/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export function NonTransitTrip({ nonTransit }: NonTransitTripProps) {
size="pill"
href={`/assistant/${nonTransit.compressedQuery}`}
title={`${modeText} ${durationShort}`}
testID={`non-transit-pill-${mode}`}
icon={{
left: <TransportMonoIcon mode={{ transportMode: mode }} />,
right: <MonoIcon icon="navigation/ArrowRight" />,
Expand Down
20 changes: 14 additions & 6 deletions src/page-modules/assistant/server/trip-cache.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import TTLCache from '@isaacs/ttlcache';
import { FromToTripQuery, TripData } from '../types';
import { createTripQuery, tripQueryToQueryString } from '../utils';

let tripCache: TTLCache<string, TripData> | null = null;

Expand All @@ -15,16 +14,25 @@ function getTripCacheInstance(): TTLCache<string, TripData> {
export function getAssistantTripIfCached(
query: FromToTripQuery,
): TripData | undefined {
const queryString = tripQueryToQueryString(createTripQuery(query));
if (tripCache?.has(`/api/assistant/trip?${queryString}`)) {
return tripCache.get(`/api/assistant/trip?${queryString}`);
const cacheKey = createCacheKey(query);
if (tripCache?.has(cacheKey)) {
return tripCache.get(cacheKey);
}
}

export function addAssistantTripToCache(
query: FromToTripQuery,
tripData: TripData,
) {
const queryString = tripQueryToQueryString(createTripQuery(query));
getTripCacheInstance().set(`/api/assistant/trip?${queryString}`, tripData);
getTripCacheInstance().set(createCacheKey(query), tripData);
}

function createCacheKey(valuesToCreateCacheKey: FromToTripQuery) {
const keys = Object.keys(valuesToCreateCacheKey).sort();
const values = keys.map(
(key) => valuesToCreateCacheKey[key as keyof FromToTripQuery],
);
const cacheKey = JSON.stringify(values);

return 'assistant-trip-' + Buffer.from(cacheKey).toString('base64');
}
1 change: 1 addition & 0 deletions src/page-modules/assistant/trip/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ export default function Trip({ tripQuery, fallback }: TripProps) {
tripPattern={tripPattern}
delay={i * 0.1}
index={i}
testId={`tripPattern-${tripIndex}-${i}`}
/>
</div>
)),
Expand Down
4 changes: 3 additions & 1 deletion src/page-modules/assistant/trip/trip-pattern/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@ type TripPatternProps = {
tripPattern: TripPatternType;
delay: number;
index: number;
testId?: string;
};

export default function TripPattern({
tripPattern,
delay,
index,
testId,
}: TripPatternProps) {
const { t, language } = useTranslation();

Expand Down Expand Up @@ -70,7 +72,7 @@ export default function TripPattern({
<motion.a
href={`/assistant/${tripPattern.compressedQuery}`}
className={className}
data-testid={`trip-pattern-${index}`}
data-testid={testId}
initial={{ opacity: 0, x: -10 }}
animate={{ opacity: maxOpacity, x: 0 }}
exit={{ opacity: 0, x: -10 }}
Expand Down

0 comments on commit 6f89a59

Please sign in to comment.