Skip to content

Commit

Permalink
Merge pull request #4 from parkerdavis1/dev
Browse files Browse the repository at this point in the history
Handle geolocation error, handle timezone error, add tests
  • Loading branch information
parkerdavis1 authored Feb 11, 2024
2 parents d16aa9e + 122ee0b commit 7964133
Show file tree
Hide file tree
Showing 10 changed files with 100 additions and 35 deletions.
3 changes: 3 additions & 0 deletions playwright.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ const config = {
command: 'npm run build && npm run preview',
port: 4173
},
use: {
permissions: ['geolocation']
},
testDir: 'tests',
testMatch: /(.+\.)?(test|spec)\.[jt]s/
};
Expand Down
9 changes: 7 additions & 2 deletions src/lib/components/PreComponents/FormLocate.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,11 @@
console.log(position.coords);
$preFormInput.latlon = `${position.coords.latitude},${position.coords.longitude}`;
};
await navigator.geolocation.getCurrentPosition(success, error, options);
try {
await navigator.geolocation.getCurrentPosition(success, error, options);
} catch (error) {
console.error(error);
}
};
</script>

Expand Down Expand Up @@ -81,7 +85,8 @@
</button>
{#if locateError.error}
<span class="locate-error">
{#if locateError.code === 1}{$_('pre_submit.locate_error')} {/if}({locateError.message})
{#if locateError.code === 1}{$_('pre_submit.locate_error')}
{/if}({locateError.message})
</span>
{/if}

Expand Down
2 changes: 1 addition & 1 deletion src/lib/components/PreComponents/PreInputForm.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
if (result.type === 'failure') {
// render error text
if (
result.data.type === 'Timezone Offset Error' ||
result.data.type === 'timezoneOffsetError' ||
result.data.type === 'GetWeatherForStartAndEnd error'
) {
$preErrorText = result.data.message;
Expand Down
23 changes: 23 additions & 0 deletions src/lib/services/timezone.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { test, expect } from 'vitest';
import { find } from 'geo-tz';

test('Timezone is able to be found with some edge case GPS coordinates', () => {
// threw error in RainCrow with geo-tz 8.0.1
expect(find(41.796014, -87.576506)).toStrictEqual(['America/Chicago']);
// threw error in RainCrow with geo-tz 8.0.1
expect(find(24.597694, -81.583389)).toStrictEqual(['America/New_York']);
// threw error in RainCrow with geo-tz 8.0.1
expect(find(24.566016, -81.673234)).toStrictEqual(['America/New_York']);
// gave problems on github issue apparently
expect(find(-24.244125928804735, -53.8226425697034)).toStrictEqual(['America/Sao_Paulo']);
// gave problems on github issue apparently
expect(find(34.05861, -118.3928)).toStrictEqual(['America/Los_Angeles']);
// Edge of Reservation Land in NE AZ (Rez)
expect(find(35.1578900375291, -111.24227457293293)).toStrictEqual(['America/Denver']);
// Edge of Reservation Land in NE AZ (Non-rez)
expect(find(35.15698602683568, -111.24796115826194)).toStrictEqual(['America/Phoenix']);
// Middle of the Atlantic Ocean
expect(find(43.298646833300026, -38.425597455498185)).toStrictEqual(['Etc/GMT+3']);
// CA/AZ border
expect(find(33.608429524254916, -114.53309086102836)).toStrictEqual(['America/Los_Angeles']);
});
11 changes: 10 additions & 1 deletion src/lib/services/validation.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
import { parseLatlon } from './parseLatlon';

export const validateLatlon = (latlon) => {
const latlonRegex = /\s*-?\d+\.\d+,\s*-?\d+\.\d+\s*/;
return latlon.match(latlonRegex) ? true : false;
const textFormatCheck = latlon.match(latlonRegex) ? true : false;
const { lat, lon } = parseLatlon(latlon);
const latNum = parseInt(lat);
const lonNum = parseInt(lon);
const latNumCheck = latNum >= -90 && latNum <= 90;
const lonNumCheck = lonNum >= -180 && lonNum <= 180;

return textFormatCheck && latNumCheck && lonNumCheck;
};

export const validateDate = (date) => {
Expand Down
15 changes: 15 additions & 0 deletions src/lib/services/validation.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { describe, expect, test } from 'vitest';
import { validateLatlon } from './validation';

describe('Validate Lat Lon', () => {
test('validates valid lat lon', () => {
expect(validateLatlon('33.33, -22.22')).toBe(true);
expect(validateLatlon('33.0, -82.2')).toBe(true);
});
test('Rejects invalid latlon', () => {
expect(validateLatlon('-91.00, 111.11')).toBe(false);
expect(validateLatlon('91.00, 111.11')).toBe(false);
expect(validateLatlon('44.4, -181.0')).toBe(false);
expect(validateLatlon('44.4, 181.0')).toBe(false);
});
});
12 changes: 9 additions & 3 deletions src/routes/postGetWeather.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,19 @@ export default async function postGetWeather({ fetch, request, cookies }) {
console.log('dayjsTimes', dayjsTimes);

// ---- Get unixtime from timezone ----
const tz = find(postWeather.location.lat, postWeather.location.lon);
console.log('timezone', tz);
let tz;
try {
tz = find(postWeather.location.lat, postWeather.location.lon);
} catch (error) {
return fail(400, {
type: 'timezoneOffsetError',
message: 'Error getting time zone for checklist coordinates'
});
}
dayjsTimes.start.unixTime = dayjsTimes.start.localTime.tz(tz, true).unix();
if (dayjsTimes.end.localTime) {
dayjsTimes.end.unixTime = dayjsTimes.end.localTime.tz(tz, true).unix();
}
console.log('unixTimes included', dayjsTimes);

// ---- Query weather ----
postWeather.weatherResults = await getWeatherForStartAndEnd(postWeather, dayjsTimes, fetch);
Expand Down
11 changes: 10 additions & 1 deletion src/routes/preGetWeather.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,16 @@ export default async function preGetWeather({ fetch, request, cookies }) {
dayjsTimes.end.localTime = dayjs(dayjsTimes.start.localTime).add(duration, 'minute');

// ---- Get unixtime from timezone ----
const tz = find(preWeather.location.lat, preWeather.location.lon);
let tz;
try {
tz = find(preWeather.location.lat, preWeather.location.lon);
} catch (error) {
return fail(400, {
...errorObj,
type: 'timezoneOffsetError',
message: 'Error getting time zone for given coordinates'
});
}
dayjsTimes.start.unixTime = dayjsTimes.start.localTime.tz(tz, true).unix();
if (dayjsTimes.end.localTime) {
dayjsTimes.end.unixTime = dayjsTimes.end.localTime.tz(tz, true).unix();
Expand Down
22 changes: 22 additions & 0 deletions tests/geolocation.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { expect, test } from '@playwright/test';

test('Error is displayed when user denies geolocation', async ({ page }) => {
await page.goto('/');
await page.getByRole('button', { name: 'Pre-Submit' }).click();
await page.getByRole('button', { name: 'Locate' }).click();
await expect(page.getByText('Allow location access to use')).toBeVisible();
});

test.describe('When Geolocation is granted', () => {
test.use({
geolocation: { longitude: 41.890221, latitude: 12.492348 },
permissions: ['geolocation']
});

test('Locate button works and fills out the input', async ({ page }) => {
await page.goto('/');
await page.getByRole('button', { name: 'Pre-Submit' }).click();
await page.getByRole('button', { name: 'Locate' }).click();
await expect(page.getByLabel('Location (Latitude, Longitude)')).not.toBeEmpty();
});
});
27 changes: 0 additions & 27 deletions tests/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,30 +10,3 @@ test('index page has nav bar', async ({ page }) => {
await expect(page.getByRole('button', { name: 'Submitted' })).toBeVisible();
await expect(page.getByRole('button', { name: 'Pre-Submit' })).toBeVisible();
});

test.beforeEach(async ({ context }) => {
await context.route('https://api.ebird.org/v2/**', async (route) => {
const json = {
message: { checklist: ['info'] }
};
await route.fulfill({ json });
});
await context.route(
'https://api.openweathermap.org/data/3.0/onecall/timemachine**',
async (route) => {
const json = {
weather: { results: 'hot' }
};
await route.fulfill({ json });
}
);
});

test('makes mock API request', async ({ page }) => {
await page.goto('/');
await page.getByRole('button', { name: 'Submitted' }).click();
await page.getByLabel('Checklist ID:').click();
await page.getByLabel('Checklist ID:').fill('https://ebird.org/checklist/S142104802');
await page.getByRole('button', { name: 'Get Weather' }).click();
await expect(page.getByTestId('weatherResultsPane').toContainText('fail'));
});

0 comments on commit 7964133

Please sign in to comment.