Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add untyped part #1

Merged
merged 1 commit into from
Oct 12, 2022
Merged
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
41 changes: 41 additions & 0 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
image: node:14-alpine
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- .npm/
before_script:
- npm ci --cache .npm --prefer-offline

after_script:
- echo "After script section"
- echo "For example you might do some cleanup here"

build1:
stage: build
script:
- npm run build
artifacts:
expire_in: 1 week
paths:
- 'build/'


test1:
stage: test
script:
- "CI=true npm test"
dependencies:
- build1

pages:
stage: deploy
script:
- mv public _public
- mv build public
only:
- master
artifacts:
paths:
- public
dependencies:
- build1
21 changes: 21 additions & 0 deletions src/App.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import "./components/styles.css";
import ParentComponent from "./components/ParentComponent";
import Products from "./components/Products";

function App() {
const items = [
{ title: "Cat Food", slug: "cat-food" },
{ title: "Dog Food", slug: "dog-food" },
{ title: "Waffles", slug: "waffles" },
];

return (
<div className="app">
<h1>Shop</h1>
<Products items={items} />
<ParentComponent open data="data" />
</div>
);
}

export default App;
156 changes: 156 additions & 0 deletions src/App.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
import React from "react";
import userEvent from "@testing-library/user-event";

import { render, screen, within } from "@testing-library/react";

import App from "./App";
import * as api from "./api";
import TopLevelComponent from "./components/TopLevelComponent";

import ParentComponent from "./components/ParentComponent";
import ImageComponent from "./components/ImageComponent";
const mockChildComponent = jest.fn();

jest.mock("./components/ChildComponent", () => (props) => {
mockChildComponent(props);
return <mock-childComponent />;
});

const spyPurchaseFunction = jest.spyOn(api, "purchaseFunction");

const localStorageMock = (function () {
let store = {};

return {
getItem(key) {
return store[key];
},

setItem(key, value) {
store[key] = value;
},

clear() {
store = {};
},

removeItem(key) {
delete store[key];
},

getAll() {
return store;
},
};
})();

Object.defineProperty(window, "localStorage", { value: localStorageMock });

test("If ParentComponent is passed open and has data, ChildComponent is called with them", () => {
render(<ParentComponent open data="some data" />);
expect(mockChildComponent).toHaveBeenCalledWith(
expect.objectContaining({
open: true,
data: "some data",
})
);
});

test("If ParentComponent is not passed open, ChildComponent is not called", () => {
render(<ParentComponent />);
expect(mockChildComponent).not.toHaveBeenCalled();
});

jest.mock("./components/Modal", () => () => {
return <mock-modal data-testid="modal" />;
});

test("If TopLevelComponent is passed the open prop Modal is rendered", () => {
const { queryByTestId } = render(<TopLevelComponent open />);
expect(queryByTestId("modal")).toBeTruthy();
});

test("If TopLevelComponent is not passed the open prop Modal is not rendered", () => {
const { queryByTestId } = render(<TopLevelComponent />);
expect(queryByTestId("modal")).toBe(null);
});

test("purchaseFunction called with correct product slug on second button click", () => {
render(<App />);

// Get the dog food buy button from an array of all buy buttons.
const DogFoodButton = screen.queryAllByText("Buy Item")[1];

userEvent.click(DogFoodButton);

expect(spyPurchaseFunction).toHaveBeenCalledWith("dog-food");
});

test("purchaseFunction called with correct product slug on Dog Food click", () => {
render(<App />);

// Get the specific card and bind to query functions.
const DogFoodCard = within(screen.getByText("Dog Food").parentElement);

// Now we can click the specific button within that card.
userEvent.click(DogFoodCard.getByRole("button", { name: "Buy Item" }));

expect(spyPurchaseFunction).toHaveBeenCalledWith("dog-food");
});

describe("The image component", () => {
test("alt contains correct value", () => {
render(<ImageComponent size="large" />);
const testImage = document.querySelector("img"); // as HTMLImageElement
expect(testImage.alt).toContain("The image alt tag for the large image");
});

test("src contains correct value", () => {
render(<ImageComponent size="large" />);
const testImage = document.querySelector("img");
expect(testImage.src).toContain("https://www.example.com/image-large.png");
});
});


const setLocalStorage = (id, data) => {
window.localStorage.setItem(id, JSON.stringify(data));
};

describe("Set local storage item", () => {
beforeEach(() => {
window.localStorage.clear();
});

test("data is added into local storage", () => {
const mockId = "111";
const mockJson = { data: "json data" };
setLocalStorage(mockId, mockJson);
expect(localStorage.getItem(mockId)).toEqual(JSON.stringify(mockJson));
});

test("data in local storage which is overwritten", () => {
const mockId = "222";
const mockOldData = { data: "json data" };
const mockNewData = { data: "new data" };

window.localStorage.setItem(mockId, JSON.stringify(mockOldData));
expect(localStorage.getItem(mockId)).toEqual(JSON.stringify(mockOldData));

setLocalStorage(mockId, mockNewData);
window.localStorage.setItem(mockId, JSON.stringify(mockNewData));
});

test("only one ID is in localStorage", () => {
const mockId = "333";
const mockOldData = { data: "json data" };
const mockNewData = { data: "new data" };

window.localStorage.setItem(mockId, JSON.stringify(mockOldData));
setLocalStorage(mockId, mockNewData);

const allItems = window.localStorage.getAll();

expect(Object.keys(allItems).length).toBe(1);
});
});
1 change: 1 addition & 0 deletions src/api.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const purchaseFunction = (slug) => {};
16 changes: 16 additions & 0 deletions src/components/Card.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React from "react";
import "./styles.css"
import { purchaseFunction } from "../api";

const Card = ({ title, slug }) => {
return (
<div className="card">
<h2>{title}</h2>
<button className="button" onClick={() => purchaseFunction(slug)}>
Buy Item
</button>
</div>
);
};

export default Card;
14 changes: 14 additions & 0 deletions src/components/ChildComponent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import React from 'react';

const ChildComponent = (props) => {

return (
<div>
<p>ChildComponent</p>
{JSON.stringify(props)}
</div>
);
}

export default ChildComponent;

12 changes: 12 additions & 0 deletions src/components/ImageComponent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React from "react";

const ImageComponent = ({ size }) => {
return (
<img
src={`https://www.example.com/image-${size}.png`}
alt={`The image alt tag for the ${size} image`}
/>
);
};

export default ImageComponent;
11 changes: 11 additions & 0 deletions src/components/Modal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React from 'react';

const Modal = () => {
return (
<div>
<p>Modal component info</p>
</div>
);
}

export default Modal;
15 changes: 15 additions & 0 deletions src/components/ParentComponent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from "react";
import ChildComponent from "./ChildComponent";

const ParentComponent = ({ open, data }) => {

console.log(open)
return (
<>
<p>Some content to render</p>
{open && <ChildComponent open={open} data={data} />}
</>
);
};

export default ParentComponent;
15 changes: 15 additions & 0 deletions src/components/Products.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from "react";
import Card from "./Card";
import "./styles.css";

const Products = ({ items }) => {
return (
<div className="products">
{items.map(({ title, slug }) => (
<Card key={slug} title={title} slug={slug} />
))}
</div>
);
};

export default Products;
14 changes: 14 additions & 0 deletions src/components/TopLevelComponent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import React from 'react';
import Modal from './Modal';

const TopLevelComponent = ({ open }) => {
return (
<div>
<p>Some top level component info</p>
{open && <Modal />}

</div>
);
}

export default TopLevelComponent;
2 changes: 1 addition & 1 deletion src/components/__tests__/HiddenMessage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { CSSTransition } from "react-transition-group";
import HiddenMessage from "../HiddenMessage";
import HiddenMessage from "../typed/HiddenMessage";

jest.mock("react-transition-group", () => {
const FakeCSSTransition = jest.fn();
Expand Down
2 changes: 1 addition & 1 deletion src/components/__tests__/MainViewTranslate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {

import { render as rtlRender, RenderOptions, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import MainViewTranslate from "../MainViewTranslate";
import MainViewTranslate from "../typed/MainViewTranslate";
import i18n from "i18next";
import Backend from "i18next-xhr-backend";
import LanguageDetector from "i18next-browser-languagedetector";
Expand Down
2 changes: 1 addition & 1 deletion src/components/__tests__/NumberDisplay.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {render, screen} from '@testing-library/react'
import NumberDisplay from '../NumberDisplay'
import NumberDisplay from '../typed/NumberDisplay'

test('calling render with the same component on the same container does not remount', () => {
const {rerender} = render(<NumberDisplay number={1} />)
Expand Down
2 changes: 1 addition & 1 deletion src/components/__tests__/Portal.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { render, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import Modal from "../Portal";
import Modal from "../typed/Portal";

test("modal shows the children and a close button", async () => {
// Arrange
Expand Down
2 changes: 1 addition & 1 deletion src/components/__tests__/ReducerComp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {render, screen} from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import '@testing-library/jest-dom/extend-expect'

import FetchGreeting from '../ReducerComp'
import FetchGreeting from '../typed/ReducerComp'


const server = setupServer(
Expand Down
2 changes: 1 addition & 1 deletion src/components/__tests__/ThemeContext.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from 'react'
import {render, screen} from '@testing-library/react'
import { ThemeConsumer, ThemeContext, ThemeProvider, IThemeContext } from '../ThemeContext'
import { ThemeConsumer, ThemeContext, ThemeProvider, IThemeContext } from '../typed/ThemeContext'

/**
* Test default values by rendering a context consumer without a
Expand Down
2 changes: 1 addition & 1 deletion src/components/__tests__/UpperInput.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

import {render, screen} from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import UpperInput from '../UpperInput'
import UpperInput from '../typed/UpperInput'

test('sets the value to the upper version of the value', () => {
render(<UpperInput />)
Expand Down
Loading