Initial commit

This commit is contained in:
2022-01-18 19:14:48 +13:00
commit fce1aa4710
27 changed files with 11706 additions and 0 deletions

View File

@@ -0,0 +1,25 @@
.app-home {
padding: 10px;
}
button {
background: #5851ff;
color: white;
margin: 8px;
border: none;
font-size: 13px;
font-weight: 700;
text-transform: uppercase;
padding: 16px 20px;
border-radius: 2px;
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1), 0 3px 6px rgba(0, 0, 0, 0.08);
outline: 0;
letter-spacing: 0.04em;
transition: all 0.15s ease;
cursor: pointer;
}
button:hover {
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.1), 0 1px 3px rgba(0, 0, 0, 0.1);
transform: translateY(1px);
}

View File

@@ -0,0 +1,19 @@
import { newE2EPage } from '@stencil/core/testing';
describe('app-home', () => {
it('renders', async () => {
const page = await newE2EPage();
await page.setContent('<app-home></app-home>');
const element = await page.find('app-home');
expect(element).toHaveClass('hydrated');
});
it('contains a "Profile Page" button', async () => {
const page = await newE2EPage();
await page.setContent('<app-home></app-home>');
const element = await page.find('app-home >>> button');
expect(element.textContent).toEqual('Profile page');
});
});

View File

@@ -0,0 +1,23 @@
import { Component, h } from '@stencil/core';
@Component({
tag: 'app-home',
styleUrl: 'app-home.css',
shadow: true,
})
export class AppHome {
render() {
return (
<div class="app-home">
<p>
Welcome to the Stencil App Starter. You can use this starter to build entire apps all with web components using Stencil! Check out our docs on{' '}
<a href="https://stenciljs.com">stenciljs.com</a> to get started.
</p>
<stencil-route-link url="/profile/stencil">
<button>Profile page</button>
</stencil-route-link>
</div>
);
}
}

View File

@@ -0,0 +1,3 @@
.app-profile {
padding: 10px;
}

View File

@@ -0,0 +1,27 @@
import { newE2EPage } from '@stencil/core/testing';
describe('app-profile', () => {
it('renders', async () => {
const page = await newE2EPage();
await page.setContent('<app-profile></app-profile>');
const element = await page.find('app-profile');
expect(element).toHaveClass('hydrated');
});
it('displays the specified name', async () => {
const page = await newE2EPage({ url: '/profile/joseph' });
const profileElement = await page.find('app-root >>> app-profile');
const element = profileElement.shadowRoot.querySelector('div');
expect(element.textContent).toContain('Hello! My name is Joseph.');
});
// it('includes a div with the class "app-profile"', async () => {
// const page = await newE2EPage({ url: '/profile/joseph' });
// I would like to use a selector like this above, but it does not seem to work
// const element = await page.find('app-root >>> app-profile >>> div');
// expect(element).toHaveClass('app-profile');
// });
});

View File

@@ -0,0 +1,46 @@
import { AppProfile } from './app-profile';
import { newSpecPage } from '@stencil/core/testing';
describe('app-profile', () => {
describe('normalization', () => {
it('returns a blank string if the name is undefined', async () => {
const { rootInstance } = await newSpecPage({
components: [AppProfile],
html: '<app-profile></app-profile>',
});
expect(rootInstance.normalize(undefined)).toEqual('');
});
it('returns a blank string if the name is null', async () => {
const { rootInstance } = await newSpecPage({
components: [AppProfile],
html: '<app-profile></app-profile>',
});
expect(rootInstance.normalize(null)).toEqual('');
});
it('capitalizes the first letter', async () => {
const { rootInstance } = await newSpecPage({
components: [AppProfile],
html: '<app-profile></app-profile>',
});
expect(rootInstance.normalize('quincy')).toEqual('Quincy');
});
it('lower-cases the following letters', async () => {
const { rootInstance } = await newSpecPage({
components: [AppProfile],
html: '<app-profile></app-profile>',
});
expect(rootInstance.normalize('JOSEPH')).toEqual('Joseph');
});
it('handles single letter names', async () => {
const { rootInstance } = await newSpecPage({
components: [AppProfile],
html: '<app-profile></app-profile>',
});
expect(rootInstance.normalize('q')).toEqual('Q');
});
});
});

View File

@@ -0,0 +1,28 @@
import { Component, Prop, h } from '@stencil/core';
import { MatchResults } from '@stencil/router';
@Component({
tag: 'app-profile',
styleUrl: 'app-profile.css',
shadow: true,
})
export class AppProfile {
@Prop() match: MatchResults;
normalize(name: string): string {
if (name) {
return name.substr(0, 1).toUpperCase() + name.substr(1).toLowerCase();
}
return '';
}
render() {
if (this.match && this.match.params.name) {
return (
<div class="app-profile">
<p>Hello! My name is {this.normalize(this.match.params.name)}. My name was passed in through a route param!</p>
</div>
);
}
}
}

View File

@@ -0,0 +1,15 @@
header {
background: #5851ff;
color: white;
height: 56px;
display: flex;
align-items: center;
box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.26);
}
h1 {
font-size: 1.4rem;
font-weight: 500;
color: #fff;
padding: 0 12px;
}

View File

@@ -0,0 +1,17 @@
import { newE2EPage } from '@stencil/core/testing';
describe('app-root', () => {
it('renders', async () => {
const page = await newE2EPage({ url: '/' });
const element = await page.find('app-root');
expect(element).toHaveClass('hydrated');
});
it('renders the title', async () => {
const page = await newE2EPage({ url: '/' });
const element = await page.find('app-root >>> h1');
expect(element.textContent).toEqual('Stencil App Starter');
});
});

View File

@@ -0,0 +1,27 @@
import { Component, h } from '@stencil/core';
@Component({
tag: 'app-root',
styleUrl: 'app-root.css',
shadow: true,
})
export class AppRoot {
render() {
return (
<div>
<header>
<h1>Stencil App Starter</h1>
</header>
<main>
<stencil-router>
<stencil-route-switch scrollTopOffset={0}>
<stencil-route url="/" component="app-home" exact={true} />
<stencil-route url="/profile/:name" component="app-profile" />
</stencil-route-switch>
</stencil-router>
</main>
</div>
);
}
}