Skip to content

Commit

Permalink
Merge pull request #46 from BenjaminWatts/issue-27
Browse files Browse the repository at this point in the history
Issue 27
  • Loading branch information
BenjaminWatts authored Dec 20, 2023
2 parents a837283 + 3174447 commit b4f0949
Show file tree
Hide file tree
Showing 54 changed files with 25,058 additions and 473 deletions.
25 changes: 25 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: Jest Tests

on: [push] # Trigger the workflow on every push to the repository

jobs:
build:
runs-on: ubuntu-latest # You can choose a different OS if needed

steps:
- name: Checkout code
uses: actions/checkout@v2 # Checkout your code repository

- name: Install Node.js
uses: actions/setup-node@v2
with:
node-version: 21.1.0 # You can specify your desired Node.js version here

- name: Install dependencies
run: yarn

- name: Run Jest unit tests
run: yarn test

- name: Run Jest e2e tests
run: yarn run e2e
10 changes: 9 additions & 1 deletion .github/workflows/update.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
name: update
on: push
on:
push:
branches:
- production
- preview
workflow_run:
workflows: ["test"]
types:
- completed

jobs:
update:
Expand Down
2 changes: 1 addition & 1 deletion app/unit-group/[code]/_layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const UnitGroupTabs: React.FC<UnitGroupTabsProps> = () => {
<>
<Stack.Screen
options={{
title: unitGroup.details.name,
title: `${unitGroup.details.name}: Unit Breakdown`,
headerRight: () => <InfoModal />,


Expand Down
4 changes: 2 additions & 2 deletions app/unit-group/[code]/schedule.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useContext } from "react";
import { UnitGroupHistory } from "../../../components/UnitGroupHistory";
import { UnitGroupSchedule } from "../../../components/UnitGroupSchedule";
import { UnitGroupContext } from "../../../services/contexts";
import log from "../../../services/log";

Expand All @@ -20,7 +20,7 @@ export const UnitGroupHistoryScreen: React.FC<
log.debug(
`UnitGroupHistoryScreen: Found unitGroup ${unitGroup.details.name}`
);
return <UnitGroupHistory ug={unitGroup} />;
return <UnitGroupSchedule ug={unitGroup} />;
}
};

Expand Down
4 changes: 2 additions & 2 deletions assets/data/units.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1189,7 +1189,7 @@ export const unitGroups: UnitGroup[] = [

{
details: {
coe : "ANSU",
code : "ANSU",
name: "An Suidhe",
coords: {
lat: 56.2187,
Expand Down Expand Up @@ -3864,5 +3864,5 @@ export const unitGroups: UnitGroup[] = [
// convert to a dictionary with code as key
export const unitGroupsDict: UnitGroupsDict = {};
for (const ug of unitGroups) {
unitGroupsDict[ug.details.code] = ug;
if(ug.details.code) unitGroupsDict[ug.details.code] = ug;
}
3 changes: 3 additions & 0 deletions atoms/__snapshots__/maps.test.tsx.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`atoms/maps/UnitGroupMap can render 1`] = `undefined`;
106 changes: 106 additions & 0 deletions atoms/cards.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { render, screen, fireEvent } from "@testing-library/react-native";
import * as c from "./cards";
import { urls } from "../services/nav";

const mockLinkingOpenURL = jest.fn();
jest.mock("react-native/Libraries/Linking/Linking", () => ({
openURL: mockLinkingOpenURL,
}));

let mockLondonTime = jest.fn();
jest.mock("../common/utils", () => ({
londonTime: (x: any) => mockLondonTime(x),
}));

describe("atoms/cards/IncompleteUnknownCategories", () => {
beforeEach(() => {
render(<c.IncompleteUnknownCategories />);
mockLinkingOpenURL.mockClear();
});

test("renders text", () => {
screen.getByText("Help us!");
screen.getByText(
"This open-source app is incomplete. We need help to categorise the hundreds of individual balancing mechnism units into the right categories, giving them human readable names and plotting them on the map."
);
screen.getByText(
"All the Unknown values represents balancing mechanism units we haven't yet categorised. We need open-source contributions to complete this work."
);
screen.getByText(
"Please help us by contributing to the project on GitHub."
);
});

test("github link", () => {
const githubButton = screen.getByTestId("github-repo-link");
fireEvent.press(githubButton);
expect(mockLinkingOpenURL).toBeCalledWith(urls.githubRepo);
});
});

describe("atoms/cards/UnknownUnitGroupCode", () => {
beforeEach(() => {
render(<c.UnknownUnitGroupCode />);
});

test("renders text", () => {
screen.getByText("Error");
screen.getByText(
"Cannot find details for this generator. Please check the URL and try again."
);
});
});

describe("atoms/cards/MissingScreen", () => {
beforeEach(() => {
mockLinkingOpenURL.mockClear();
render(<c.MissingScreen />);
});

test("renders expected text", () => {
screen.getByText("Error");
screen.getByText("This screen does not exist.");
});

test("can click on home link", () => {
const homeButton = screen.getByText("Reset to Home screen");
fireEvent.press(homeButton);
expect(mockLinkingOpenURL).toBeCalledWith(urls.home);
});
});

describe("atoms/cards/UnitListHeader", () => {

test("renders loading text with undefined now prop", () => {
render(<c.UnitListHeader />);
screen.getByText("Loading data for individual units");
});

test("renders live individual unit output and local time if now prop is a Date ", () => {
const now = new Date(Date.parse("2023-01-01"));
mockLondonTime.mockReturnValue("NOW");
render(<c.UnitListHeader now={now} />);
expect(mockLondonTime).toBeCalledWith(now);
screen.getByText("Live individual unit output at NOW");
});

afterAll(() => {
mockLondonTime.mockRestore();
});
});


describe("atoms/cards/UnitGroupScheduleHeader", () => {

test('renders bmUnit code', () => {
render(<c.UnitGroupScheduleHeader bmUnit="BMU1" />);
screen.getByText("BMU1");
})

test('renders Upcoming Schedule', () => {
render(<c.UnitGroupScheduleHeader bmUnit="BMU1" />);
screen.getByText("Upcoming Schedule");
})


})
123 changes: 102 additions & 21 deletions atoms/cards.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import React from "react";
import { Button, Card, Text } from "@rneui/themed";
import { GITHUB_REPO_LINK } from "../common/links";
import { Linking, StyleSheet, View } from "react-native";
import { FontAwesome } from "@expo/vector-icons";
import log from "../services/log";
import { urls } from "../services/nav";
import { londonTime } from "../common/utils";

/*
IncompleteUnknownCategories
Render a card with a message asking for help to categorise the unknown balancing mechanism units.
*/
export const IncompleteUnknownCategories = () => {
return (
<Card>
Expand All @@ -22,8 +27,9 @@ export const IncompleteUnknownCategories = () => {
<View style={styles.spacer} />

<Text>
All the Unknown values represents balancing mechanism units
we haven't yet categorised. We need open-source contributions to complete this work.
All the Unknown values represents balancing mechanism units we haven't
yet categorised. We need open-source contributions to complete this
work.
</Text>

<View style={styles.spacer} />
Expand All @@ -33,75 +39,150 @@ export const IncompleteUnknownCategories = () => {
<View style={styles.spacer} />

<Button
onPress={() => Linking.openURL(GITHUB_REPO_LINK)}
testID="github-repo-link"
onPress={() => Linking.openURL(urls.githubRepo)}
icon={<FontAwesome name="github" size={24} color="white" />}
/>
</Card>
);
};

/*
UnknownUnitGroupCode
Render a card with a message saying we can't find the unit group.
*/
export const UnknownUnitGroupCode = () => {
log.debug(`UnknownUnitGroupCode`)
log.debug(`UnknownUnitGroupCode`);
return (
<Card>
<Card.Title>
<Text>Error</Text>
</Card.Title>
<Card.Divider />
<Text>
Cannot find details for this generator. Please check the URL and try again.
Cannot find details for this generator. Please check the URL and try
again.
</Text>
</Card>
);
};


export const MissingScreen = () => {
log.debug(`MissingScreen`)
/*
MissingScreen
Render a card with a message saying the screen doesn't exist.
*/
export const MissingScreen: React.FC = () => {
log.debug(`MissingScreen`);
return (
<Card>
<Card.Title>
<Text>Error</Text>
</Card.Title>
<Card.Divider />
<Text>
This screen does not exist.
</Text>

<Text>This screen does not exist.</Text>
<Card.Divider />
<Button
testID="reset-home-button"
onPress={() => {
Linking.openURL(urls.home);
}}
>
Reset to Home screen
</Button>
</Card>
);
};

type UnitListHeaderProps = {
now?: Date;
}
export const UnitListHeader:React.FC<UnitListHeaderProps> = ({now}) => {
};

/*
UnitListHeader
Render a card with either a loading message or the london time of the latest update
*/
export const UnitListHeader: React.FC<UnitListHeaderProps> = ({ now }) => {
const props = { testID: "unit-list-header-text" };
return (
<Card containerStyle={styles.listHeaderCard}>
{now ? <Text>Live Individual Unit output at: {now.toLocaleTimeString()}</Text> : <Text>Loading Individual Units</Text>}
{now ? (
<Text {...props} testID="unit-list-header-text">
Live individual unit output at {londonTime(now)}
</Text>
) : (
<Text {...props}>Loading data for individual units</Text>
)}
</Card>
);
}
};

type UnitGroupHistoryListHeaderComponentProps = {
bmUnit: string;
average: number;
}
export const UnitGroupHistoryListHeaderComponent:React.FC<UnitGroupHistoryListHeaderComponentProps> = ({bmUnit, average}) => {

};

/*
UnitGroupScheduleHeader
Render a card with the unit group name and the words "Upcoming Schedule"
*/
export const UnitGroupScheduleHeader: React.FC<
UnitGroupHistoryListHeaderComponentProps
> = ({ bmUnit }) => {
return (
<Card containerStyle={styles.listHeaderCard}>
<Card.Title>{bmUnit}</Card.Title>
<Card.Divider />
<Text>Upcoming Schedule</Text>
</Card>
);
};

/*
EmptyScheduleCard
*/
export const EmptyScheduleCard: React.FC = () => {
return (
<Card containerStyle={styles.listHeaderCard}>
<Card.Title>No Scheduled Output</Card.Title>
<Card.Divider />
<Text>None of the units are expected to generate/consume of the coming hours</Text>
<View style={styles.spacer} />
<Text>They may be under maintenance.</Text>
</Card>
);
};

/*
ApiError
*/
type ApiErrorProps = {
refetch: () => void;
}
export const ApiErrorCard: React.FC<ApiErrorProps> = ({ refetch }) => {
return (
<Card>
<Card.Title>
<Text>API Error</Text>
</Card.Title>
<View style={styles.spacer} />

<Text>
There was an error fetching/interpreting data from the Elexon API. Please try again later.
</Text>

<View style={styles.spacer} />


<Button onPress={refetch}>Try again</Button>
</Card>
)
}

const styles = StyleSheet.create({
spacer: { height: 10 },
listHeaderCard: {
margin: 0,
// padding: 0,
}
},
});
Loading

0 comments on commit b4f0949

Please sign in to comment.