├── .appveyor.yml
├── .circleci
└── config.yml
├── .gitignore
├── .travis.yml
├── LICENSE.md
├── README.md
├── images
├── advanced.png
└── simple.png
├── index.html
├── package.json
├── renovate.json
├── src
├── cache.ts
├── colors.ts
├── github-repository.ts
├── index.d.ts
├── license.ts
├── repo.ts
└── user.ts
├── test
├── data
│ ├── abraham
│ │ ├── empty.json
│ │ ├── twitter-status.json
│ │ └── twitteroauth.json
│ ├── angular
│ │ └── angular.json
│ ├── error.json
│ └── vuejs
│ │ └── vue.json
└── github-repository.test.ts
├── tsconfig.json
└── tsconfig.production.json
/.appveyor.yml:
--------------------------------------------------------------------------------
1 | environment:
2 | nodejs_version: "9"
3 |
4 | install:
5 | - ps: Install-Product node $env:nodejs_version
6 | - npm install
7 |
8 | test_script:
9 | - node --version
10 | - npm --version
11 | - npm test
12 |
13 | cache:
14 | - node_modules
15 | - '%APPDATA%\npm-cache'
16 |
17 | build: off
18 |
--------------------------------------------------------------------------------
/.circleci/config.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | jobs:
3 | build:
4 | macos:
5 | xcode: "11.3.1"
6 | steps:
7 | - checkout
8 | - run: brew cask install firefox google-chrome
9 | - run: node --version
10 | - run: npm --version
11 | - restore_cache:
12 | key: dependency-cache-{{ checksum "package.json" }}
13 | - run: npm install
14 | - save_cache:
15 | key: dependency-cache-{{ checksum "package.json" }}
16 | paths:
17 | - ./node_modules
18 | - run: npm run test
19 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | dist
3 | yarn.lock
4 | package-lock.json
5 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | # Work-around for https://github.com/travis-ci/travis-ci/issues/8836
2 | sudo: true
3 | language: node_js
4 | node_js:
5 | - node
6 | before_script:
7 | - node --version
8 | - npm --version
9 | - npm install
10 | script:
11 | - npm run test
12 | os:
13 | - linux
14 | cache:
15 | directories:
16 | - node_modules
17 | addons:
18 | firefox: latest
19 | chrome: stable
20 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Copyright 2017
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4 |
5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 |
7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | <github-repository>
2 | ====
3 |
4 | [](https://npmjs.com/package/github-repository)
5 | [](https://circleci.com/gh/abraham/github-repository)
6 | [](https://travis-ci.org/abraham/github-repository)
7 | [](https://ci.appveyor.com/project/abraham/github-repository)
8 | [](https://david-dm.org/abraham/github-repository)
9 | [](https://bundlephobia.com/result?p=github-repository)
10 |
11 | Install
12 | ----
13 |
14 | Polyfill tags if you need them. This will include ShadowDOM and Custom Elements support.
15 |
16 | ```
17 |
18 | ```
19 |
20 | Loading this component. It would be a good idea to use a specific version instead of `latest`.
21 |
22 | ```
23 |
24 | ```
25 |
26 | Example
27 | ----
28 |
29 | [Live demo](https://codepen.io/abraham/pen/PQoeqV)
30 |
31 | Usage
32 | ----
33 |
34 | Set the `owner-repo` attribute to the `username/repository` of a GitHub repository.
35 |
36 | ```
37 |
38 | ```
39 |
40 | 
41 |
42 | For more advanced usage you can include:
43 |
44 | - `
` to include a preview image
45 | - A number of `
` to include status badges
46 |
47 | ```
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 | ```
66 |
67 | 
68 |
69 | GitHub API Rate limit
70 | ----
71 |
72 | This Web Component makes unauthenticated requests to the GitHub API. Since the GitHub API has a fairly restrictive 60 requests/hour per IP address, API responses are cached in `localStorage`.
73 |
74 | License
75 | ----
76 |
77 | GithubRepository is released under an MIT license.
78 |
79 | Built, tested, and published with [Nutmeg](https://nutmeg.tools).
80 |
--------------------------------------------------------------------------------
/images/advanced.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/abraham/github-repository/a371d65236a3aec3de49568caa631a00d0145524/images/advanced.png
--------------------------------------------------------------------------------
/images/simple.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/abraham/github-repository/a371d65236a3aec3de49568caa631a00d0145524/images/simple.png
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | github-repository demos
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "github-repository",
3 | "version": "0.4.0",
4 | "description": "GitHub Repository Web Component",
5 | "main": "dist/github-repository.js",
6 | "module": "dist/github-repository.js",
7 | "unpkg": "dist/github-repository.min.js",
8 | "types": "dist/github-repository.d.ts",
9 | "directories": {
10 | "test": "test"
11 | },
12 | "repository": {
13 | "type": "git",
14 | "url": "git+https://github.com/abraham/github-repository.git"
15 | },
16 | "engines": {
17 | "node": ">=8.0.0"
18 | },
19 | "keywords": [
20 | "github-repository",
21 | "github",
22 | "nutmeg",
23 | "web-component"
24 | ],
25 | "license": "MIT",
26 | "bugs": {
27 | "url": "https://github.com/abraham/github-repository/issues"
28 | },
29 | "homepage": "https://github.com/abraham/github-repository",
30 | "scripts": {
31 | "build": "npx nutmeg build .",
32 | "prebuild": "npx nutmeg clean .",
33 | "prepare": "npm run build -- --production",
34 | "pretest": "npm run build",
35 | "start": "npx nutmeg serve .",
36 | "test": "npx nutmeg test .",
37 | "watch": "npx nutmeg watch ."
38 | },
39 | "dependencies": {
40 | "@nutmeg/seed": "0.17.0",
41 | "approximate-number": "2.1.0"
42 | },
43 | "devDependencies": {
44 | "@nutmeg/cli": "0.17.0"
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "config:base"
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/src/cache.ts:
--------------------------------------------------------------------------------
1 | import { GithubRepository } from './github-repository';
2 | import { RepoData } from './repo';
3 |
4 | export class Cache {
5 | private readonly CACHE_LENGTH = 24 * 60 * 60 * 1000;
6 | private githubRepository: GithubRepository;
7 |
8 | constructor(githubRepository: GithubRepository) {
9 | this.githubRepository = githubRepository;
10 | }
11 |
12 | public get data(): RepoData | null {
13 | return this.cache.data;
14 | }
15 |
16 | public set data(data: RepoData | null) {
17 | if (!data) { return }
18 | const cache = {
19 | data: data,
20 | cachedAt: Date.now(),
21 | };
22 | localStorage.setItem(this.cacheKey, JSON.stringify(cache))
23 | }
24 |
25 | public get expired(): boolean {
26 | return this.cachedAt < Date.now() - this.CACHE_LENGTH;
27 | }
28 |
29 | private get cachedAt(): number {
30 | return this.cache.cachedAt || Date.now();
31 | }
32 |
33 | private get cache(): RepoCache {
34 | const cache = localStorage.getItem(this.cacheKey);
35 | if (cache) {
36 | return JSON.parse(cache) as RepoCache;
37 | } else {
38 | return {
39 | cachedAt: 0,
40 | data: null,
41 | };
42 | }
43 | }
44 |
45 | private get cacheKey(): string {
46 | return `github-repository_${this.githubRepository.ownerRepo}_cache`;
47 | }
48 | }
49 |
50 | interface RepoCache {
51 | cachedAt: number;
52 | data: RepoData | null;
53 | }
54 |
--------------------------------------------------------------------------------
/src/colors.ts:
--------------------------------------------------------------------------------
1 | export class Colors {
2 | public static language(language: string): string {
3 | return (this.colors as any)[language] || '#ccc';
4 | }
5 |
6 | private static readonly colors = {
7 | '1C Enterprise': '#814CCC',
8 | 'ABAP': '#E8274B',
9 | 'ActionScript': '#882B0F',
10 | 'Ada': '#02f88c',
11 | 'Agda': '#315665',
12 | 'AGS Script': '#B9D9FF',
13 | 'Alloy': '#64C800',
14 | 'AMPL': '#E6EFBB',
15 | 'ANTLR': '#9DC3FF',
16 | 'API Blueprint': '#2ACCA8',
17 | 'APL': '#5A8164',
18 | 'AppleScript': '#101F1F',
19 | 'Arc': '#aa2afe',
20 | 'Arduino': '#bd79d1',
21 | 'ASP': '#6a40fd',
22 | 'AspectJ': '#a957b0',
23 | 'Assembly': '#6E4C13',
24 | 'ATS': '#1ac620',
25 | 'AutoHotkey': '#6594b9',
26 | 'AutoIt': '#1C3552',
27 | 'Ballerina': '#FF5000',
28 | 'Batchfile': '#C1F12E',
29 | 'BlitzMax': '#cd6400',
30 | 'Boo': '#d4bec1',
31 | 'Brainfuck': '#2F2530',
32 | 'C': '#555555',
33 | 'C#': '#178600',
34 | 'C++': '#f34b7d',
35 | 'Ceylon': '#dfa535',
36 | 'Chapel': '#8dc63f',
37 | 'Cirru': '#ccccff',
38 | 'Clarion': '#db901e',
39 | 'Clean': '#3F85AF',
40 | 'Click': '#E4E6F3',
41 | 'Clojure': '#db5855',
42 | 'CoffeeScript': '#244776',
43 | 'ColdFusion': '#ed2cd6',
44 | 'Common Lisp': '#3fb68b',
45 | 'Component Pascal': '#B0CE4E',
46 | 'Crystal': '#776791',
47 | 'CSS': '#563d7c',
48 | 'Cuda': '#3A4E3A',
49 | 'D': '#ba595e',
50 | 'Dart': '#00B4AB',
51 | 'DataWeave': '#003a52',
52 | 'DM': '#447265',
53 | 'Dogescript': '#cca760',
54 | 'Dylan': '#6c616e',
55 | 'E': '#ccce35',
56 | 'eC': '#913960',
57 | 'ECL': '#8a1267',
58 | 'Eiffel': '#946d57',
59 | 'Elixir': '#6e4a7e',
60 | 'Elm': '#60B5CC',
61 | 'Emacs Lisp': '#c065db',
62 | 'EmberScript': '#FFF4F3',
63 | 'EQ': '#a78649',
64 | 'Erlang': '#B83998',
65 | 'F#': '#b845fc',
66 | 'Factor': '#636746',
67 | 'Fancy': '#7b9db4',
68 | 'Fantom': '#14253c',
69 | 'FLUX': '#88ccff',
70 | 'Forth': '#341708',
71 | 'Fortran': '#4d41b1',
72 | 'FreeMarker': '#0050b2',
73 | 'Frege': '#00cafe',
74 | 'Game Maker Language': '#8fb200',
75 | 'Genie': '#fb855d',
76 | 'Gherkin': '#5B2063',
77 | 'Glyph': '#e4cc98',
78 | 'Gnuplot': '#f0a9f0',
79 | 'Go': '#375eab',
80 | 'Golo': '#88562A',
81 | 'Gosu': '#82937f',
82 | 'Grammatical Framework': '#79aa7a',
83 | 'Groovy': '#e69f56',
84 | 'Hack': '#878787',
85 | 'Harbour': '#0e60e3',
86 | 'Haskell': '#5e5086',
87 | 'Haxe': '#df7900',
88 | 'HTML': '#e34c26',
89 | 'Hy': '#7790B2',
90 | 'IDL': '#a3522f',
91 | 'Io': '#a9188d',
92 | 'Ioke': '#078193',
93 | 'Isabelle': '#FEFE00',
94 | 'J': '#9EEDFF',
95 | 'Java': '#b07219',
96 | 'JavaScript': '#f1e05a',
97 | 'Jolie': '#843179',
98 | 'JSONiq': '#40d47e',
99 | 'Julia': '#a270ba',
100 | 'Jupyter Notebook': '#DA5B0B',
101 | 'Kotlin': '#F18E33',
102 | 'KRL': '#28431f',
103 | 'Lasso': '#999999',
104 | 'Lex': '#DBCA00',
105 | 'LiveScript': '#499886',
106 | 'LLVM': '#185619',
107 | 'LOLCODE': '#cc9900',
108 | 'LookML': '#652B81',
109 | 'LSL': '#3d9970',
110 | 'Lua': '#000080',
111 | 'Makefile': '#427819',
112 | 'Mask': '#f97732',
113 | 'Matlab': '#e16737',
114 | 'Max': '#c4a79c',
115 | 'MAXScript': '#00a6a6',
116 | 'Mercury': '#ff2b2b',
117 | 'Meson': '#007800',
118 | 'Metal': '#8f14e9',
119 | 'Mirah': '#c7a938',
120 | 'MQL4': '#62A8D6',
121 | 'MQL5': '#4A76B8',
122 | 'MTML': '#b7e1f4',
123 | 'NCL': '#28431f',
124 | 'Nearley': '#990000',
125 | 'Nemerle': '#3d3c6e',
126 | 'nesC': '#94B0C7',
127 | 'NetLinx': '#0aa0ff',
128 | 'NetLinx+ERB': '#747faa',
129 | 'NetLogo': '#ff6375',
130 | 'NewLisp': '#87AED7',
131 | 'Nim': '#37775b',
132 | 'Nit': '#009917',
133 | 'Nix': '#7e7eff',
134 | 'Nu': '#c9df40',
135 | 'Objective-C': '#438eff',
136 | 'Objective-C++': '#6866fb',
137 | 'Objective-J': '#ff0c5a',
138 | 'OCaml': '#3be133',
139 | 'Omgrofl': '#cabbff',
140 | 'ooc': '#b0b77e',
141 | 'Opal': '#f7ede0',
142 | 'Oxygene': '#cdd0e3',
143 | 'Oz': '#fab738',
144 | 'P4': '#7055b5',
145 | 'Pan': '#cc0000',
146 | 'Papyrus': '#6600cc',
147 | 'Parrot': '#f3ca0a',
148 | 'Pascal': '#E3F171',
149 | 'PAWN': '#dbb284',
150 | 'Pep8': '#C76F5B',
151 | 'Perl': '#0298c3',
152 | 'Perl 6': '#0000fb',
153 | 'PHP': '#4F5D95',
154 | 'PigLatin': '#fcd7de',
155 | 'Pike': '#005390',
156 | 'PLSQL': '#dad8d8',
157 | 'PogoScript': '#d80074',
158 | 'PostScript': '#da291c',
159 | 'PowerBuilder': '#8f0f8d',
160 | 'PowerShell': '#012456',
161 | 'Processing': '#0096D8',
162 | 'Prolog': '#74283c',
163 | 'Propeller Spin': '#7fa2a7',
164 | 'Puppet': '#302B6D',
165 | 'PureBasic': '#5a6986',
166 | 'PureScript': '#1D222D',
167 | 'Python': '#3572A5',
168 | 'QML': '#44a51c',
169 | 'R': '#198CE7',
170 | 'Racket': '#22228f',
171 | 'Ragel': '#9d5200',
172 | 'RAML': '#77d9fb',
173 | 'Rascal': '#fffaa0',
174 | 'Rebol': '#358a5b',
175 | 'Red': '#f50000',
176 | "Ren'Py": '#ff7f7f',
177 | 'Ring': '#0e60e3',
178 | 'Roff': '#ecdebe',
179 | 'Rouge': '#cc0088',
180 | 'Ruby': '#701516',
181 | 'RUNOFF': '#665a4e',
182 | 'Rust': '#dea584',
183 | 'SaltStack': '#646464',
184 | 'SAS': '#B34936',
185 | 'Scala': '#c22d40',
186 | 'Scheme': '#1e4aec',
187 | 'Self': '#0579aa',
188 | 'Shell': '#89e051',
189 | 'Shen': '#120F14',
190 | 'Slash': '#007eff',
191 | 'Smalltalk': '#596706',
192 | 'SourcePawn': '#5c7611',
193 | 'SQF': '#3F3F3F',
194 | 'Squirrel': '#800000',
195 | 'SRecode Template': '#348a34',
196 | 'Stan': '#b2011d',
197 | 'Standard ML': '#dc566d',
198 | 'SuperCollider': '#46390b',
199 | 'Swift': '#ffac45',
200 | 'SystemVerilog': '#DAE1C2',
201 | 'Tcl': '#e4cc98',
202 | 'Terra': '#00004c',
203 | 'TeX': '#3D6117',
204 | 'TI Program': '#A0AA87',
205 | 'Turing': '#cf142b',
206 | 'TypeScript': '#2b7489',
207 | 'UnrealScript': '#a54c4d',
208 | 'Vala': '#fbe5cd',
209 | 'Verilog': '#b2b7f8',
210 | 'VHDL': '#adb2cb',
211 | 'Vim script': '#199f4b',
212 | 'Visual Basic': '#945db7',
213 | 'Volt': '#1F1F1F',
214 | 'Vue': '#2c3e50',
215 | 'WebAssembly': '#04133b',
216 | 'wisp': '#7582D1',
217 | 'X10': '#4B6BEF',
218 | 'xBase': '#403a40',
219 | 'XC': '#99DA07',
220 | 'XQuery': '#5232e7',
221 | 'XSLT': '#EB8CEB',
222 | 'Yacc': '#4B6C4B',
223 | 'Zephir': '#118f9e'
224 | }
225 | }
226 |
--------------------------------------------------------------------------------
/src/github-repository.ts:
--------------------------------------------------------------------------------
1 | import { Seed, property, html, svg, TemplateResult } from '@nutmeg/seed';
2 | import approximateNumber from 'approximate-number';
3 |
4 | import { Cache } from './cache';
5 | import { EmptyRepo, Repo, RepoData } from './repo';
6 |
7 | export class GithubRepository extends Seed {
8 | @property({ type: String }) public ownerRepo: string = '';
9 |
10 | private _repo: Repo | EmptyRepo = new EmptyRepo();
11 | private cache: Cache;
12 | private error: string | undefined;
13 | private pending = false;
14 |
15 | constructor() {
16 | super();
17 | this.cache = new Cache(this);
18 | }
19 |
20 | /** The component instance has been inserted into the DOM. */
21 | public connectedCallback() {
22 | super.connectedCallback();
23 | }
24 |
25 | /** The component instance has been removed from the DOM. */
26 | public disconnectedCallback() {
27 | super.disconnectedCallback();
28 | }
29 |
30 | /** Watch for changes to these attributes. */
31 | public static get observedAttributes(): string[] {
32 | return super.observedAttributes;
33 | }
34 |
35 | /** Rerender when the observed attributes change. */
36 | public attributeChangedCallback(name: string, oldValue: any, newValue: any) {
37 | super.attributeChangedCallback(name, oldValue, newValue);
38 | }
39 |
40 | private get repo(): Repo | EmptyRepo {
41 | if (this.cache.data && !!this.ownerRepo && this.ownerRepo !== this._repo.fullName) {
42 | this._repo = new Repo(this.cache.data);
43 | }
44 | if (!this._repo || this.cache.expired || this.ownerRepo !== this._repo.fullName) {
45 | this.fetchRepository();
46 | }
47 | return this._repo;
48 | }
49 |
50 | private async fetchRepository(): Promise {
51 | if (this.pending || !this.ownerRepo) {
52 | return;
53 | }
54 | this.pending = true;
55 | const response = await fetch(`https://api.github.com/repos/${this.ownerRepo}`);
56 | const data = await response.json();
57 | if (response.status === 200) {
58 | this._repo = new Repo(data);
59 | this.cache.data = data;
60 | } else {
61 | this.error = data.message;
62 | }
63 | this.pending = false;
64 | this.render();
65 | }
66 |
67 | private countDisplay(count: number): string {
68 | return approximateNumber(count);
69 | }
70 |
71 | /** Styling for the component. */
72 | public get styles(): TemplateResult {
73 | return html`
74 |
293 | `;
294 | }
295 |
296 | private get logo(): TemplateResult {
297 | return svg`
298 |
302 | `;
303 | }
304 |
305 | private get issuesIcon(): TemplateResult {
306 | return svg`
307 |
310 | `;
311 | }
312 |
313 | private get forkIcon(): TemplateResult {
314 | return svg`
315 |
318 | `;
319 | }
320 |
321 | private get starIcon(): TemplateResult {
322 | return html`
323 |
326 | `;
327 | }
328 |
329 | private get watchIcon(): TemplateResult {
330 | return html`
331 |
334 | `;
335 | }
336 |
337 | private get headerTemplate(): TemplateResult {
338 | return html`
339 |
346 | `;
347 | }
348 |
349 | private get descriptionTemplate(): TemplateResult {
350 | return html`
351 |
352 |
353 | ${this.repo.description}
354 | ${this.repo.homepage ? this.homepageTempate : ''}
355 |
356 |
357 | `;
358 | }
359 |
360 | private get homepageTempate(): TemplateResult {
361 | return html`
362 |
363 | ${this.repo.displayHomepage}
364 |
365 | `;
366 | }
367 |
368 | private get cloneTemplate(): TemplateResult {
369 | return html`
370 |
371 |
${this.repo.sshUrl}
372 |
373 | `;
374 | }
375 |
376 | private get countsTemplate(): TemplateResult {
377 | return html`
378 |
396 | `;
397 | }
398 |
399 | private get languageTemplate(): TemplateResult {
400 | return html`
401 |
402 |
403 | ${this.repo.language}
404 |
405 | `;
406 | }
407 |
408 | private get footerTemplate(): TemplateResult {
409 | return html`
410 |
415 | `;
416 | }
417 |
418 | private get errorTemplate(): TemplateResult {
419 | return html`
420 |
421 |
422 |
"${this.error}"
423 |
424 | `;
425 | }
426 |
427 | private get loadingTemplate(): TemplateResult {
428 | return html`
429 |
430 |
431 |
432 |
433 |
434 |
435 |
436 |
437 |
438 |
439 |
440 |
441 |
442 |
443 | `;
444 | }
445 |
446 | private get contentTemplate(): TemplateResult {
447 | return html`
448 |
449 |
450 | ${this.headerTemplate}
451 | ${this.descriptionTemplate}
452 | ${this.countsTemplate}
453 | ${this.cloneTemplate}
454 |
455 |
456 |
457 | ${this.footerTemplate}
458 |
459 | `;
460 | }
461 |
462 | /** HTML Template for the component. */
463 | public get template(): TemplateResult {
464 | if (this.error) {
465 | return this.errorTemplate;
466 | } else if (!!this.repo.fullName) {
467 | return this.contentTemplate;
468 | } else {
469 | return this.loadingTemplate;
470 | }
471 | }
472 | }
473 |
474 | window.customElements.define('github-repository', GithubRepository);
475 |
--------------------------------------------------------------------------------
/src/index.d.ts:
--------------------------------------------------------------------------------
1 | declare module 'approximate-number' {
2 | function approximateNumber(num: number, opts?: {}): string;
3 | export default approximateNumber;
4 | }
5 |
--------------------------------------------------------------------------------
/src/license.ts:
--------------------------------------------------------------------------------
1 | export class License {
2 | private data: LicenseData;
3 |
4 | constructor(license: LicenseData) {
5 | this.data = license;
6 | }
7 |
8 | public get name(): string {
9 | return this.data ? this.data.name : 'Unknown license';
10 | }
11 | }
12 |
13 | export interface LicenseData {
14 | key: string;
15 | name: string;
16 | spdx_id: string;
17 | url: string;
18 | }
19 |
--------------------------------------------------------------------------------
/src/repo.ts:
--------------------------------------------------------------------------------
1 | import { Colors } from './colors';
2 | import { User, UserData } from './user';
3 | import { License, LicenseData } from './license';
4 |
5 | export class Repo {
6 | public owner: User;
7 | private readonly months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
8 | private license: License;
9 |
10 | constructor(private data: RepoData) {
11 | this.license = new License(data.license);
12 | this.owner = new User(data.owner);
13 | }
14 |
15 | public get name(): string {
16 | return this.data.name;
17 | }
18 |
19 | public get fullName(): string {
20 | return this.data.full_name;
21 | }
22 |
23 | public get htmlUrl(): string {
24 | return this.data.html_url;
25 | }
26 |
27 | public get description(): string {
28 | return this.data.description;
29 | }
30 |
31 | public get sshUrl(): string {
32 | return this.data.ssh_url;
33 | }
34 |
35 | public get displayPushedAt(): string {
36 | const month = this.months[this.pushedAt.getMonth()];
37 | return `${month} ${this.pushedAt.getDate()} ${this.pushedYear}`;
38 | }
39 |
40 | public get homepage(): string {
41 | return this.data.homepage;
42 | }
43 |
44 | public get displayHomepage(): string {
45 | return (this.homepage || '')
46 | .replace('http://www.', '')
47 | .replace('https://www.', '')
48 | .replace('http://', '')
49 | .replace('https://', '');
50 | }
51 |
52 | public get starsCount(): number {
53 | return this.data.stargazers_count;
54 | }
55 |
56 | public get watchersCount(): number {
57 | return this.data.subscribers_count;
58 | }
59 |
60 | public get openIssuesCount(): number {
61 | return this.data.open_issues_count;
62 | }
63 |
64 | public get forksCount(): number {
65 | return this.data.forks_count;
66 | }
67 |
68 | public get language(): string {
69 | return this.data.language || 'Unknown language';
70 | }
71 |
72 | public get languageColor(): string {
73 | return Colors.language(this.data.language);
74 | }
75 |
76 | public get displayLicense(): string {
77 | return this.license.name;
78 | }
79 |
80 | private get pushedAt(): Date {
81 | return new Date(Date.parse(this.data.pushed_at));
82 | }
83 |
84 | private get pushedYear(): string {
85 | return (new Date()).getFullYear() === this.pushedAt.getFullYear() ? '' : `${this.pushedAt.getFullYear()}`;
86 | }
87 | }
88 |
89 | export class EmptyRepo {
90 | public id = 0;
91 | public fullName = '';
92 | public owner = { htmlUrl: '', login: '' };
93 | public htmlUrl = '';
94 | public name = '';
95 | public description = '';
96 | public homepage = '';
97 | public displayHomepage = '';
98 | public sshUrl = '';
99 | public watchersCount = 0;
100 | public starsCount = 0;
101 | public openIssuesCount = 0;
102 | public forksCount = 0;
103 | public language = '';
104 | public languageColor = '';
105 | public displayPushedAt = '';
106 | public displayLicense = '';
107 | };
108 |
109 | export interface RepoData {
110 | id: number;
111 | name: string;
112 | full_name: string;
113 | owner: UserData;
114 | private: boolean;
115 | html_url: string;
116 | description: string;
117 | fork: boolean;
118 | url: string;
119 | forks_url: string;
120 | keys_url: string;
121 | collaborators_url: string;
122 | teams_url: string;
123 | hooks_url: string;
124 | issue_events_url: string;
125 | events_url: string;
126 | assignees_url: string;
127 | branches_url: string;
128 | tags_url: string;
129 | blobs_url: string;
130 | git_tags_url: string;
131 | git_refs_url: string;
132 | trees_url: string;
133 | statuses_url: string;
134 | languages_url: string;
135 | stargazers_url: string;
136 | contributors_url: string;
137 | subscribers_url: string;
138 | subscription_url: string;
139 | commits_url: string;
140 | git_commits_url: string;
141 | comments_url: string;
142 | issue_comment_url: string;
143 | contents_url: string;
144 | compare_url: string;
145 | merges_url: string;
146 | archive_url: string;
147 | downloads_url: string;
148 | issues_url: string;
149 | pulls_url: string;
150 | milestones_url: string;
151 | notifications_url: string;
152 | labels_url: string;
153 | releases_url: string;
154 | deployments_url: string;
155 | created_at: string;
156 | updated_at: string;
157 | pushed_at: string;
158 | git_url: string;
159 | ssh_url: string;
160 | clone_url: string;
161 | svn_url: string;
162 | homepage: string;
163 | size: number;
164 | stargazers_count: number;
165 | watchers_count: number;
166 | language: string;
167 | has_issues: boolean;
168 | has_projects: boolean;
169 | has_downloads: boolean;
170 | has_wiki: boolean;
171 | has_pages: boolean;
172 | forks_count: number;
173 | mirror_url: string | null;
174 | archived: boolean;
175 | open_issues_count: number;
176 | license: LicenseData;
177 | forks: number;
178 | open_issues: number;
179 | watchers: number;
180 | default_branch: string;
181 | network_count: number;
182 | subscribers_count: number;
183 | }
184 |
--------------------------------------------------------------------------------
/src/user.ts:
--------------------------------------------------------------------------------
1 | export class User {
2 | private data: UserData;
3 |
4 | constructor(user: UserData) {
5 | this.data = user;
6 | }
7 |
8 | public get htmlUrl(): string {
9 | return this.data.html_url;
10 | }
11 |
12 | public get login(): string {
13 | return this.data.login;
14 | }
15 | }
16 |
17 | export interface UserData {
18 | login: string;
19 | id: number;
20 | avatar_url: string;
21 | gravatar_id: string;
22 | url: string;
23 | html_url: string;
24 | followers_url: string;
25 | following_url: string;
26 | gists_url: string;
27 | starred_url: string;
28 | subscriptions_url: string;
29 | organizations_url: string;
30 | repos_url: string;
31 | events_url: string;
32 | received_events_url: string;
33 | type: 'User'
34 | site_admin: boolean;
35 | }
36 |
--------------------------------------------------------------------------------
/test/data/abraham/empty.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": 119274896,
3 | "name": "empty",
4 | "full_name": "abraham/empty",
5 | "owner": {
6 | "login": "abraham",
7 | "id": 3341,
8 | "avatar_url": "https://avatars1.githubusercontent.com/u/3341?v=4",
9 | "gravatar_id": "",
10 | "url": "https://api.github.com/users/abraham",
11 | "html_url": "https://github.com/abraham",
12 | "followers_url": "https://api.github.com/users/abraham/followers",
13 | "following_url": "https://api.github.com/users/abraham/following{/other_user}",
14 | "gists_url": "https://api.github.com/users/abraham/gists{/gist_id}",
15 | "starred_url": "https://api.github.com/users/abraham/starred{/owner}{/repo}",
16 | "subscriptions_url": "https://api.github.com/users/abraham/subscriptions",
17 | "organizations_url": "https://api.github.com/users/abraham/orgs",
18 | "repos_url": "https://api.github.com/users/abraham/repos",
19 | "events_url": "https://api.github.com/users/abraham/events{/privacy}",
20 | "received_events_url": "https://api.github.com/users/abraham/received_events",
21 | "type": "User",
22 | "site_admin": false
23 | },
24 | "private": false,
25 | "html_url": "https://github.com/abraham/empty",
26 | "description": null,
27 | "fork": false,
28 | "url": "https://api.github.com/repos/abraham/empty",
29 | "forks_url": "https://api.github.com/repos/abraham/empty/forks",
30 | "keys_url": "https://api.github.com/repos/abraham/empty/keys{/key_id}",
31 | "collaborators_url": "https://api.github.com/repos/abraham/empty/collaborators{/collaborator}",
32 | "teams_url": "https://api.github.com/repos/abraham/empty/teams",
33 | "hooks_url": "https://api.github.com/repos/abraham/empty/hooks",
34 | "issue_events_url": "https://api.github.com/repos/abraham/empty/issues/events{/number}",
35 | "events_url": "https://api.github.com/repos/abraham/empty/events",
36 | "assignees_url": "https://api.github.com/repos/abraham/empty/assignees{/user}",
37 | "branches_url": "https://api.github.com/repos/abraham/empty/branches{/branch}",
38 | "tags_url": "https://api.github.com/repos/abraham/empty/tags",
39 | "blobs_url": "https://api.github.com/repos/abraham/empty/git/blobs{/sha}",
40 | "git_tags_url": "https://api.github.com/repos/abraham/empty/git/tags{/sha}",
41 | "git_refs_url": "https://api.github.com/repos/abraham/empty/git/refs{/sha}",
42 | "trees_url": "https://api.github.com/repos/abraham/empty/git/trees{/sha}",
43 | "statuses_url": "https://api.github.com/repos/abraham/empty/statuses/{sha}",
44 | "languages_url": "https://api.github.com/repos/abraham/empty/languages",
45 | "stargazers_url": "https://api.github.com/repos/abraham/empty/stargazers",
46 | "contributors_url": "https://api.github.com/repos/abraham/empty/contributors",
47 | "subscribers_url": "https://api.github.com/repos/abraham/empty/subscribers",
48 | "subscription_url": "https://api.github.com/repos/abraham/empty/subscription",
49 | "commits_url": "https://api.github.com/repos/abraham/empty/commits{/sha}",
50 | "git_commits_url": "https://api.github.com/repos/abraham/empty/git/commits{/sha}",
51 | "comments_url": "https://api.github.com/repos/abraham/empty/comments{/number}",
52 | "issue_comment_url": "https://api.github.com/repos/abraham/empty/issues/comments{/number}",
53 | "contents_url": "https://api.github.com/repos/abraham/empty/contents/{+path}",
54 | "compare_url": "https://api.github.com/repos/abraham/empty/compare/{base}...{head}",
55 | "merges_url": "https://api.github.com/repos/abraham/empty/merges",
56 | "archive_url": "https://api.github.com/repos/abraham/empty/{archive_format}{/ref}",
57 | "downloads_url": "https://api.github.com/repos/abraham/empty/downloads",
58 | "issues_url": "https://api.github.com/repos/abraham/empty/issues{/number}",
59 | "pulls_url": "https://api.github.com/repos/abraham/empty/pulls{/number}",
60 | "milestones_url": "https://api.github.com/repos/abraham/empty/milestones{/number}",
61 | "notifications_url": "https://api.github.com/repos/abraham/empty/notifications{?since,all,participating}",
62 | "labels_url": "https://api.github.com/repos/abraham/empty/labels{/name}",
63 | "releases_url": "https://api.github.com/repos/abraham/empty/releases{/id}",
64 | "deployments_url": "https://api.github.com/repos/abraham/empty/deployments",
65 | "created_at": "2017-01-28T16:17:12Z",
66 | "updated_at": "2017-01-28T16:17:12Z",
67 | "pushed_at": "2017-01-28T16:17:13Z",
68 | "git_url": "git://github.com/abraham/empty.git",
69 | "ssh_url": "git@github.com:abraham/empty.git",
70 | "clone_url": "https://github.com/abraham/empty.git",
71 | "svn_url": "https://github.com/abraham/empty",
72 | "homepage": null,
73 | "size": 0,
74 | "stargazers_count": 0,
75 | "watchers_count": 0,
76 | "language": null,
77 | "has_issues": true,
78 | "has_projects": true,
79 | "has_downloads": true,
80 | "has_wiki": true,
81 | "has_pages": false,
82 | "forks_count": 0,
83 | "mirror_url": null,
84 | "archived": false,
85 | "open_issues_count": 0,
86 | "license": null,
87 | "forks": 0,
88 | "open_issues": 0,
89 | "watchers": 0,
90 | "default_branch": "master",
91 | "network_count": 0,
92 | "subscribers_count": 1
93 | }
94 |
--------------------------------------------------------------------------------
/test/data/abraham/twitter-status.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": 117631949,
3 | "name": "twitter-status",
4 | "full_name": "abraham/twitter-status",
5 | "owner": {
6 | "login": "abraham",
7 | "id": 3341,
8 | "avatar_url": "https://avatars1.githubusercontent.com/u/3341?v=4",
9 | "gravatar_id": "",
10 | "url": "https://api.github.com/users/abraham",
11 | "html_url": "https://github.com/abraham",
12 | "followers_url": "https://api.github.com/users/abraham/followers",
13 | "following_url": "https://api.github.com/users/abraham/following{/other_user}",
14 | "gists_url": "https://api.github.com/users/abraham/gists{/gist_id}",
15 | "starred_url": "https://api.github.com/users/abraham/starred{/owner}{/repo}",
16 | "subscriptions_url": "https://api.github.com/users/abraham/subscriptions",
17 | "organizations_url": "https://api.github.com/users/abraham/orgs",
18 | "repos_url": "https://api.github.com/users/abraham/repos",
19 | "events_url": "https://api.github.com/users/abraham/events{/privacy}",
20 | "received_events_url": "https://api.github.com/users/abraham/received_events",
21 | "type": "User",
22 | "site_admin": false
23 | },
24 | "private": false,
25 | "html_url": "https://github.com/abraham/twitter-status",
26 | "description": "Twitter Status Web Component",
27 | "fork": false,
28 | "url": "https://api.github.com/repos/abraham/twitter-status",
29 | "forks_url": "https://api.github.com/repos/abraham/twitter-status/forks",
30 | "keys_url": "https://api.github.com/repos/abraham/twitter-status/keys{/key_id}",
31 | "collaborators_url": "https://api.github.com/repos/abraham/twitter-status/collaborators{/collaborator}",
32 | "teams_url": "https://api.github.com/repos/abraham/twitter-status/teams",
33 | "hooks_url": "https://api.github.com/repos/abraham/twitter-status/hooks",
34 | "issue_events_url": "https://api.github.com/repos/abraham/twitter-status/issues/events{/number}",
35 | "events_url": "https://api.github.com/repos/abraham/twitter-status/events",
36 | "assignees_url": "https://api.github.com/repos/abraham/twitter-status/assignees{/user}",
37 | "branches_url": "https://api.github.com/repos/abraham/twitter-status/branches{/branch}",
38 | "tags_url": "https://api.github.com/repos/abraham/twitter-status/tags",
39 | "blobs_url": "https://api.github.com/repos/abraham/twitter-status/git/blobs{/sha}",
40 | "git_tags_url": "https://api.github.com/repos/abraham/twitter-status/git/tags{/sha}",
41 | "git_refs_url": "https://api.github.com/repos/abraham/twitter-status/git/refs{/sha}",
42 | "trees_url": "https://api.github.com/repos/abraham/twitter-status/git/trees{/sha}",
43 | "statuses_url": "https://api.github.com/repos/abraham/twitter-status/statuses/{sha}",
44 | "languages_url": "https://api.github.com/repos/abraham/twitter-status/languages",
45 | "stargazers_url": "https://api.github.com/repos/abraham/twitter-status/stargazers",
46 | "contributors_url": "https://api.github.com/repos/abraham/twitter-status/contributors",
47 | "subscribers_url": "https://api.github.com/repos/abraham/twitter-status/subscribers",
48 | "subscription_url": "https://api.github.com/repos/abraham/twitter-status/subscription",
49 | "commits_url": "https://api.github.com/repos/abraham/twitter-status/commits{/sha}",
50 | "git_commits_url": "https://api.github.com/repos/abraham/twitter-status/git/commits{/sha}",
51 | "comments_url": "https://api.github.com/repos/abraham/twitter-status/comments{/number}",
52 | "issue_comment_url": "https://api.github.com/repos/abraham/twitter-status/issues/comments{/number}",
53 | "contents_url": "https://api.github.com/repos/abraham/twitter-status/contents/{+path}",
54 | "compare_url": "https://api.github.com/repos/abraham/twitter-status/compare/{base}...{head}",
55 | "merges_url": "https://api.github.com/repos/abraham/twitter-status/merges",
56 | "archive_url": "https://api.github.com/repos/abraham/twitter-status/{archive_format}{/ref}",
57 | "downloads_url": "https://api.github.com/repos/abraham/twitter-status/downloads",
58 | "issues_url": "https://api.github.com/repos/abraham/twitter-status/issues{/number}",
59 | "pulls_url": "https://api.github.com/repos/abraham/twitter-status/pulls{/number}",
60 | "milestones_url": "https://api.github.com/repos/abraham/twitter-status/milestones{/number}",
61 | "notifications_url": "https://api.github.com/repos/abraham/twitter-status/notifications{?since,all,participating}",
62 | "labels_url": "https://api.github.com/repos/abraham/twitter-status/labels{/name}",
63 | "releases_url": "https://api.github.com/repos/abraham/twitter-status/releases{/id}",
64 | "deployments_url": "https://api.github.com/repos/abraham/twitter-status/deployments",
65 | "created_at": "2018-01-16T04:39:27Z",
66 | "updated_at": "2018-01-27T16:36:54Z",
67 | "pushed_at": "2018-01-27T23:55:32Z",
68 | "git_url": "git://github.com/abraham/twitter-status.git",
69 | "ssh_url": "git@github.com:abraham/twitter-status.git",
70 | "clone_url": "https://github.com/abraham/twitter-status.git",
71 | "svn_url": "https://github.com/abraham/twitter-status",
72 | "homepage": "https://www.npmjs.com/package/twitter-status",
73 | "size": 1418,
74 | "stargazers_count": 5,
75 | "watchers_count": 5,
76 | "language": "TypeScript",
77 | "has_issues": true,
78 | "has_projects": true,
79 | "has_downloads": true,
80 | "has_wiki": false,
81 | "has_pages": false,
82 | "forks_count": 1,
83 | "mirror_url": null,
84 | "archived": false,
85 | "open_issues_count": 6,
86 | "license": {
87 | "key": "mit",
88 | "name": "MIT License",
89 | "spdx_id": "MIT",
90 | "url": "https://api.github.com/licenses/mit"
91 | },
92 | "forks": 1,
93 | "open_issues": 6,
94 | "watchers": 5,
95 | "default_branch": "master",
96 | "network_count": 1,
97 | "subscribers_count": 1
98 | }
99 |
--------------------------------------------------------------------------------
/test/data/abraham/twitteroauth.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": 128818,
3 | "name": "twitteroauth",
4 | "full_name": "abraham/twitteroauth",
5 | "owner": {
6 | "login": "abraham",
7 | "id": 3341,
8 | "avatar_url": "https://avatars1.githubusercontent.com/u/3341?v=4",
9 | "gravatar_id": "",
10 | "url": "https://api.github.com/users/abraham",
11 | "html_url": "https://github.com/abraham",
12 | "followers_url": "https://api.github.com/users/abraham/followers",
13 | "following_url": "https://api.github.com/users/abraham/following{/other_user}",
14 | "gists_url": "https://api.github.com/users/abraham/gists{/gist_id}",
15 | "starred_url": "https://api.github.com/users/abraham/starred{/owner}{/repo}",
16 | "subscriptions_url": "https://api.github.com/users/abraham/subscriptions",
17 | "organizations_url": "https://api.github.com/users/abraham/orgs",
18 | "repos_url": "https://api.github.com/users/abraham/repos",
19 | "events_url": "https://api.github.com/users/abraham/events{/privacy}",
20 | "received_events_url": "https://api.github.com/users/abraham/received_events",
21 | "type": "User",
22 | "site_admin": false
23 | },
24 | "private": false,
25 | "html_url": "https://github.com/abraham/twitteroauth",
26 | "description": "The most popular PHP library for use with the Twitter OAuth REST API.",
27 | "fork": false,
28 | "url": "https://api.github.com/repos/abraham/twitteroauth",
29 | "forks_url": "https://api.github.com/repos/abraham/twitteroauth/forks",
30 | "keys_url": "https://api.github.com/repos/abraham/twitteroauth/keys{/key_id}",
31 | "collaborators_url": "https://api.github.com/repos/abraham/twitteroauth/collaborators{/collaborator}",
32 | "teams_url": "https://api.github.com/repos/abraham/twitteroauth/teams",
33 | "hooks_url": "https://api.github.com/repos/abraham/twitteroauth/hooks",
34 | "issue_events_url": "https://api.github.com/repos/abraham/twitteroauth/issues/events{/number}",
35 | "events_url": "https://api.github.com/repos/abraham/twitteroauth/events",
36 | "assignees_url": "https://api.github.com/repos/abraham/twitteroauth/assignees{/user}",
37 | "branches_url": "https://api.github.com/repos/abraham/twitteroauth/branches{/branch}",
38 | "tags_url": "https://api.github.com/repos/abraham/twitteroauth/tags",
39 | "blobs_url": "https://api.github.com/repos/abraham/twitteroauth/git/blobs{/sha}",
40 | "git_tags_url": "https://api.github.com/repos/abraham/twitteroauth/git/tags{/sha}",
41 | "git_refs_url": "https://api.github.com/repos/abraham/twitteroauth/git/refs{/sha}",
42 | "trees_url": "https://api.github.com/repos/abraham/twitteroauth/git/trees{/sha}",
43 | "statuses_url": "https://api.github.com/repos/abraham/twitteroauth/statuses/{sha}",
44 | "languages_url": "https://api.github.com/repos/abraham/twitteroauth/languages",
45 | "stargazers_url": "https://api.github.com/repos/abraham/twitteroauth/stargazers",
46 | "contributors_url": "https://api.github.com/repos/abraham/twitteroauth/contributors",
47 | "subscribers_url": "https://api.github.com/repos/abraham/twitteroauth/subscribers",
48 | "subscription_url": "https://api.github.com/repos/abraham/twitteroauth/subscription",
49 | "commits_url": "https://api.github.com/repos/abraham/twitteroauth/commits{/sha}",
50 | "git_commits_url": "https://api.github.com/repos/abraham/twitteroauth/git/commits{/sha}",
51 | "comments_url": "https://api.github.com/repos/abraham/twitteroauth/comments{/number}",
52 | "issue_comment_url": "https://api.github.com/repos/abraham/twitteroauth/issues/comments{/number}",
53 | "contents_url": "https://api.github.com/repos/abraham/twitteroauth/contents/{+path}",
54 | "compare_url": "https://api.github.com/repos/abraham/twitteroauth/compare/{base}...{head}",
55 | "merges_url": "https://api.github.com/repos/abraham/twitteroauth/merges",
56 | "archive_url": "https://api.github.com/repos/abraham/twitteroauth/{archive_format}{/ref}",
57 | "downloads_url": "https://api.github.com/repos/abraham/twitteroauth/downloads",
58 | "issues_url": "https://api.github.com/repos/abraham/twitteroauth/issues{/number}",
59 | "pulls_url": "https://api.github.com/repos/abraham/twitteroauth/pulls{/number}",
60 | "milestones_url": "https://api.github.com/repos/abraham/twitteroauth/milestones{/number}",
61 | "notifications_url": "https://api.github.com/repos/abraham/twitteroauth/notifications{?since,all,participating}",
62 | "labels_url": "https://api.github.com/repos/abraham/twitteroauth/labels{/name}",
63 | "releases_url": "https://api.github.com/repos/abraham/twitteroauth/releases{/id}",
64 | "deployments_url": "https://api.github.com/repos/abraham/twitteroauth/deployments",
65 | "created_at": "2009-02-14T12:27:24Z",
66 | "updated_at": "2018-01-28T15:59:13Z",
67 | "pushed_at": "2018-01-09T02:40:48Z",
68 | "git_url": "git://github.com/abraham/twitteroauth.git",
69 | "ssh_url": "git@github.com:abraham/twitteroauth.git",
70 | "clone_url": "https://github.com/abraham/twitteroauth.git",
71 | "svn_url": "https://github.com/abraham/twitteroauth",
72 | "homepage": "https://twitteroauth.com",
73 | "size": 1233,
74 | "stargazers_count": 3551,
75 | "watchers_count": 3551,
76 | "language": "PHP",
77 | "has_issues": true,
78 | "has_projects": true,
79 | "has_downloads": true,
80 | "has_wiki": false,
81 | "has_pages": false,
82 | "forks_count": 1577,
83 | "mirror_url": null,
84 | "archived": false,
85 | "open_issues_count": 56,
86 | "license": {
87 | "key": "mit",
88 | "name": "MIT License",
89 | "spdx_id": "MIT",
90 | "url": "https://api.github.com/licenses/mit"
91 | },
92 | "forks": 1577,
93 | "open_issues": 56,
94 | "watchers": 3551,
95 | "default_branch": "master",
96 | "network_count": 1577,
97 | "subscribers_count": 221
98 | }
99 |
--------------------------------------------------------------------------------
/test/data/angular/angular.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": 24195339,
3 | "name": "angular",
4 | "full_name": "angular/angular",
5 | "owner": {
6 | "login": "angular",
7 | "id": 139426,
8 | "avatar_url": "https://avatars3.githubusercontent.com/u/139426?v=4",
9 | "gravatar_id": "",
10 | "url": "https://api.github.com/users/angular",
11 | "html_url": "https://github.com/angular",
12 | "followers_url": "https://api.github.com/users/angular/followers",
13 | "following_url": "https://api.github.com/users/angular/following{/other_user}",
14 | "gists_url": "https://api.github.com/users/angular/gists{/gist_id}",
15 | "starred_url": "https://api.github.com/users/angular/starred{/owner}{/repo}",
16 | "subscriptions_url": "https://api.github.com/users/angular/subscriptions",
17 | "organizations_url": "https://api.github.com/users/angular/orgs",
18 | "repos_url": "https://api.github.com/users/angular/repos",
19 | "events_url": "https://api.github.com/users/angular/events{/privacy}",
20 | "received_events_url": "https://api.github.com/users/angular/received_events",
21 | "type": "Organization",
22 | "site_admin": false
23 | },
24 | "private": false,
25 | "html_url": "https://github.com/angular/angular",
26 | "description": "One framework. Mobile & desktop.",
27 | "fork": false,
28 | "url": "https://api.github.com/repos/angular/angular",
29 | "forks_url": "https://api.github.com/repos/angular/angular/forks",
30 | "keys_url": "https://api.github.com/repos/angular/angular/keys{/key_id}",
31 | "collaborators_url": "https://api.github.com/repos/angular/angular/collaborators{/collaborator}",
32 | "teams_url": "https://api.github.com/repos/angular/angular/teams",
33 | "hooks_url": "https://api.github.com/repos/angular/angular/hooks",
34 | "issue_events_url": "https://api.github.com/repos/angular/angular/issues/events{/number}",
35 | "events_url": "https://api.github.com/repos/angular/angular/events",
36 | "assignees_url": "https://api.github.com/repos/angular/angular/assignees{/user}",
37 | "branches_url": "https://api.github.com/repos/angular/angular/branches{/branch}",
38 | "tags_url": "https://api.github.com/repos/angular/angular/tags",
39 | "blobs_url": "https://api.github.com/repos/angular/angular/git/blobs{/sha}",
40 | "git_tags_url": "https://api.github.com/repos/angular/angular/git/tags{/sha}",
41 | "git_refs_url": "https://api.github.com/repos/angular/angular/git/refs{/sha}",
42 | "trees_url": "https://api.github.com/repos/angular/angular/git/trees{/sha}",
43 | "statuses_url": "https://api.github.com/repos/angular/angular/statuses/{sha}",
44 | "languages_url": "https://api.github.com/repos/angular/angular/languages",
45 | "stargazers_url": "https://api.github.com/repos/angular/angular/stargazers",
46 | "contributors_url": "https://api.github.com/repos/angular/angular/contributors",
47 | "subscribers_url": "https://api.github.com/repos/angular/angular/subscribers",
48 | "subscription_url": "https://api.github.com/repos/angular/angular/subscription",
49 | "commits_url": "https://api.github.com/repos/angular/angular/commits{/sha}",
50 | "git_commits_url": "https://api.github.com/repos/angular/angular/git/commits{/sha}",
51 | "comments_url": "https://api.github.com/repos/angular/angular/comments{/number}",
52 | "issue_comment_url": "https://api.github.com/repos/angular/angular/issues/comments{/number}",
53 | "contents_url": "https://api.github.com/repos/angular/angular/contents/{+path}",
54 | "compare_url": "https://api.github.com/repos/angular/angular/compare/{base}...{head}",
55 | "merges_url": "https://api.github.com/repos/angular/angular/merges",
56 | "archive_url": "https://api.github.com/repos/angular/angular/{archive_format}{/ref}",
57 | "downloads_url": "https://api.github.com/repos/angular/angular/downloads",
58 | "issues_url": "https://api.github.com/repos/angular/angular/issues{/number}",
59 | "pulls_url": "https://api.github.com/repos/angular/angular/pulls{/number}",
60 | "milestones_url": "https://api.github.com/repos/angular/angular/milestones{/number}",
61 | "notifications_url": "https://api.github.com/repos/angular/angular/notifications{?since,all,participating}",
62 | "labels_url": "https://api.github.com/repos/angular/angular/labels{/name}",
63 | "releases_url": "https://api.github.com/repos/angular/angular/releases{/id}",
64 | "deployments_url": "https://api.github.com/repos/angular/angular/deployments",
65 | "created_at": "2014-09-18T16:12:01Z",
66 | "updated_at": "2018-01-28T20:25:49Z",
67 | "pushed_at": "2018-01-28T16:48:17Z",
68 | "git_url": "git://github.com/angular/angular.git",
69 | "ssh_url": "git@github.com:angular/angular.git",
70 | "clone_url": "https://github.com/angular/angular.git",
71 | "svn_url": "https://github.com/angular/angular",
72 | "homepage": "https://angular.io",
73 | "size": 72588,
74 | "stargazers_count": 32460,
75 | "watchers_count": 32460,
76 | "language": "TypeScript",
77 | "has_issues": true,
78 | "has_projects": true,
79 | "has_downloads": true,
80 | "has_wiki": false,
81 | "has_pages": false,
82 | "forks_count": 8018,
83 | "mirror_url": null,
84 | "archived": false,
85 | "open_issues_count": 2097,
86 | "license": {
87 | "key": "mit",
88 | "name": "MIT License",
89 | "spdx_id": "MIT",
90 | "url": "https://api.github.com/licenses/mit"
91 | },
92 | "forks": 8018,
93 | "open_issues": 2097,
94 | "watchers": 32460,
95 | "default_branch": "master",
96 | "organization": {
97 | "login": "angular",
98 | "id": 139426,
99 | "avatar_url": "https://avatars3.githubusercontent.com/u/139426?v=4",
100 | "gravatar_id": "",
101 | "url": "https://api.github.com/users/angular",
102 | "html_url": "https://github.com/angular",
103 | "followers_url": "https://api.github.com/users/angular/followers",
104 | "following_url": "https://api.github.com/users/angular/following{/other_user}",
105 | "gists_url": "https://api.github.com/users/angular/gists{/gist_id}",
106 | "starred_url": "https://api.github.com/users/angular/starred{/owner}{/repo}",
107 | "subscriptions_url": "https://api.github.com/users/angular/subscriptions",
108 | "organizations_url": "https://api.github.com/users/angular/orgs",
109 | "repos_url": "https://api.github.com/users/angular/repos",
110 | "events_url": "https://api.github.com/users/angular/events{/privacy}",
111 | "received_events_url": "https://api.github.com/users/angular/received_events",
112 | "type": "Organization",
113 | "site_admin": false
114 | },
115 | "network_count": 8018,
116 | "subscribers_count": 2851
117 | }
118 |
--------------------------------------------------------------------------------
/test/data/error.json:
--------------------------------------------------------------------------------
1 | {
2 | "message": "API rate limit exceeded for 71.90.116.85. (But here's the good news: Authenticated requests get a higher rate limit. Check out the documentation for more details.)",
3 | "documentation_url": "https://developer.github.com/v3/#rate-limiting"
4 | }
5 |
--------------------------------------------------------------------------------
/test/data/vuejs/vue.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": 11730342,
3 | "name": "vue",
4 | "full_name": "vuejs/vue",
5 | "owner": {
6 | "login": "vuejs",
7 | "id": 6128107,
8 | "avatar_url": "https://avatars1.githubusercontent.com/u/6128107?v=4",
9 | "gravatar_id": "",
10 | "url": "https://api.github.com/users/vuejs",
11 | "html_url": "https://github.com/vuejs",
12 | "followers_url": "https://api.github.com/users/vuejs/followers",
13 | "following_url": "https://api.github.com/users/vuejs/following{/other_user}",
14 | "gists_url": "https://api.github.com/users/vuejs/gists{/gist_id}",
15 | "starred_url": "https://api.github.com/users/vuejs/starred{/owner}{/repo}",
16 | "subscriptions_url": "https://api.github.com/users/vuejs/subscriptions",
17 | "organizations_url": "https://api.github.com/users/vuejs/orgs",
18 | "repos_url": "https://api.github.com/users/vuejs/repos",
19 | "events_url": "https://api.github.com/users/vuejs/events{/privacy}",
20 | "received_events_url": "https://api.github.com/users/vuejs/received_events",
21 | "type": "Organization",
22 | "site_admin": false
23 | },
24 | "private": false,
25 | "html_url": "https://github.com/vuejs/vue",
26 | "description": "🖖 A progressive, incrementally-adoptable JavaScript framework for building UI on the web.",
27 | "fork": false,
28 | "url": "https://api.github.com/repos/vuejs/vue",
29 | "forks_url": "https://api.github.com/repos/vuejs/vue/forks",
30 | "keys_url": "https://api.github.com/repos/vuejs/vue/keys{/key_id}",
31 | "collaborators_url": "https://api.github.com/repos/vuejs/vue/collaborators{/collaborator}",
32 | "teams_url": "https://api.github.com/repos/vuejs/vue/teams",
33 | "hooks_url": "https://api.github.com/repos/vuejs/vue/hooks",
34 | "issue_events_url": "https://api.github.com/repos/vuejs/vue/issues/events{/number}",
35 | "events_url": "https://api.github.com/repos/vuejs/vue/events",
36 | "assignees_url": "https://api.github.com/repos/vuejs/vue/assignees{/user}",
37 | "branches_url": "https://api.github.com/repos/vuejs/vue/branches{/branch}",
38 | "tags_url": "https://api.github.com/repos/vuejs/vue/tags",
39 | "blobs_url": "https://api.github.com/repos/vuejs/vue/git/blobs{/sha}",
40 | "git_tags_url": "https://api.github.com/repos/vuejs/vue/git/tags{/sha}",
41 | "git_refs_url": "https://api.github.com/repos/vuejs/vue/git/refs{/sha}",
42 | "trees_url": "https://api.github.com/repos/vuejs/vue/git/trees{/sha}",
43 | "statuses_url": "https://api.github.com/repos/vuejs/vue/statuses/{sha}",
44 | "languages_url": "https://api.github.com/repos/vuejs/vue/languages",
45 | "stargazers_url": "https://api.github.com/repos/vuejs/vue/stargazers",
46 | "contributors_url": "https://api.github.com/repos/vuejs/vue/contributors",
47 | "subscribers_url": "https://api.github.com/repos/vuejs/vue/subscribers",
48 | "subscription_url": "https://api.github.com/repos/vuejs/vue/subscription",
49 | "commits_url": "https://api.github.com/repos/vuejs/vue/commits{/sha}",
50 | "git_commits_url": "https://api.github.com/repos/vuejs/vue/git/commits{/sha}",
51 | "comments_url": "https://api.github.com/repos/vuejs/vue/comments{/number}",
52 | "issue_comment_url": "https://api.github.com/repos/vuejs/vue/issues/comments{/number}",
53 | "contents_url": "https://api.github.com/repos/vuejs/vue/contents/{+path}",
54 | "compare_url": "https://api.github.com/repos/vuejs/vue/compare/{base}...{head}",
55 | "merges_url": "https://api.github.com/repos/vuejs/vue/merges",
56 | "archive_url": "https://api.github.com/repos/vuejs/vue/{archive_format}{/ref}",
57 | "downloads_url": "https://api.github.com/repos/vuejs/vue/downloads",
58 | "issues_url": "https://api.github.com/repos/vuejs/vue/issues{/number}",
59 | "pulls_url": "https://api.github.com/repos/vuejs/vue/pulls{/number}",
60 | "milestones_url": "https://api.github.com/repos/vuejs/vue/milestones{/number}",
61 | "notifications_url": "https://api.github.com/repos/vuejs/vue/notifications{?since,all,participating}",
62 | "labels_url": "https://api.github.com/repos/vuejs/vue/labels{/name}",
63 | "releases_url": "https://api.github.com/repos/vuejs/vue/releases{/id}",
64 | "deployments_url": "https://api.github.com/repos/vuejs/vue/deployments",
65 | "created_at": "2013-07-29T03:24:51Z",
66 | "updated_at": "2018-01-28T19:22:08Z",
67 | "pushed_at": "2018-01-28T15:21:27Z",
68 | "git_url": "git://github.com/vuejs/vue.git",
69 | "ssh_url": "git@github.com:vuejs/vue.git",
70 | "clone_url": "https://github.com/vuejs/vue.git",
71 | "svn_url": "https://github.com/vuejs/vue",
72 | "homepage": "http://vuejs.org",
73 | "size": 22346,
74 | "stargazers_count": 81783,
75 | "watchers_count": 81783,
76 | "language": "JavaScript",
77 | "has_issues": true,
78 | "has_projects": true,
79 | "has_downloads": true,
80 | "has_wiki": false,
81 | "has_pages": false,
82 | "forks_count": 12013,
83 | "mirror_url": null,
84 | "archived": false,
85 | "open_issues_count": 124,
86 | "license": {
87 | "key": "mit",
88 | "name": "MIT License",
89 | "spdx_id": "MIT",
90 | "url": "https://api.github.com/licenses/mit"
91 | },
92 | "forks": 12013,
93 | "open_issues": 124,
94 | "watchers": 81783,
95 | "default_branch": "dev",
96 | "organization": {
97 | "login": "vuejs",
98 | "id": 6128107,
99 | "avatar_url": "https://avatars1.githubusercontent.com/u/6128107?v=4",
100 | "gravatar_id": "",
101 | "url": "https://api.github.com/users/vuejs",
102 | "html_url": "https://github.com/vuejs",
103 | "followers_url": "https://api.github.com/users/vuejs/followers",
104 | "following_url": "https://api.github.com/users/vuejs/following{/other_user}",
105 | "gists_url": "https://api.github.com/users/vuejs/gists{/gist_id}",
106 | "starred_url": "https://api.github.com/users/vuejs/starred{/owner}{/repo}",
107 | "subscriptions_url": "https://api.github.com/users/vuejs/subscriptions",
108 | "organizations_url": "https://api.github.com/users/vuejs/orgs",
109 | "repos_url": "https://api.github.com/users/vuejs/repos",
110 | "events_url": "https://api.github.com/users/vuejs/events{/privacy}",
111 | "received_events_url": "https://api.github.com/users/vuejs/received_events",
112 | "type": "Organization",
113 | "site_admin": false
114 | },
115 | "network_count": 12013,
116 | "subscribers_count": 4421
117 | }
118 |
--------------------------------------------------------------------------------
/test/github-repository.test.ts:
--------------------------------------------------------------------------------
1 | import 'mocha';
2 | import { expect } from 'chai';
3 | import * as sinon from 'sinon';
4 |
5 | import { GithubRepository } from '../src/github-repository';
6 |
7 | // Increase timeout for AppVeyor
8 | const TIMEOUT = 500;
9 |
10 | describe('', () => {
11 | let component: GithubRepository;
12 | let stub: sinon.SinonStub;
13 |
14 | beforeEach(async () => {
15 | localStorage.clear();
16 | const realFetch = window.fetch;
17 | stub = sinon.stub(window, 'fetch').callsFake(async (url: string) => {
18 | const ownerRepo = url.replace('https://api.github.com/repos/', '');
19 | return realFetch(`./base/test/data/${ownerRepo}.json`);
20 | });
21 | });
22 |
23 | afterEach(() => {
24 | stub.restore();
25 | });
26 |
27 | describe('without properties', () => {
28 | beforeEach(() => {
29 | component = fixture('');
30 | });
31 |
32 | it('renders loading', () => {
33 | expect(component.$('#loader')).to.exist;
34 | expect(component.$('.animated-background')).to.exist;
35 | expect(component.$$('.background-masker').length).to.eq(8);
36 | });
37 | });
38 |
39 | describe('with owner-repo', () => {
40 | beforeEach(async () => {
41 | component = fixture('');
42 | await sleep(TIMEOUT);
43 | });
44 |
45 | it('renders the header', () => {
46 | const links = component.$$('#header a') as NodeListOf;
47 | expect(links.length).to.eq(3);
48 | expect(links[0].href).to.eq('https://github.com/abraham');
49 | expect(links[0].innerText).to.eq('abraham');
50 | expect(links[1].href).to.eq('https://github.com/abraham/twitter-status');
51 | expect(links[1].innerText).to.eq('twitter-status');
52 | expect(links[2].href).to.eq('https://github.com/abraham/twitter-status');
53 | expect(links[2].querySelector('svg').getAttribute('aria-label')).to.eq('GitHub');
54 | });
55 |
56 | it('renders the description', () => {
57 | expect(component.$('#description').innerText).to.eq('Twitter Status Web Component npmjs.com/package/twitter-status');
58 | });
59 |
60 | it('renders the homepage', () => {
61 | const link = component.$('#homepage a') as HTMLAnchorElement;
62 | expect(link.href).to.eq('https://www.npmjs.com/package/twitter-status');
63 | expect(link.innerText).to.eq('npmjs.com/package/twitter-status');
64 | });
65 |
66 | it('renders the counters', () => {
67 | const links = component.$$('#counters a') as NodeListOf;
68 | expect(links.length).to.eq(4);
69 | expect(links[0].href).to.eq('https://github.com/abraham/twitter-status/watchers');
70 | expect(links[0].innerText.trim()).to.eq('Watchers\n1');
71 | expect(links[1].href).to.eq('https://github.com/abraham/twitter-status/stargazers');
72 | expect(links[1].innerText.trim()).to.eq('Stars\n5');
73 | expect(links[2].href).to.eq('https://github.com/abraham/twitter-status/network');
74 | expect(links[2].innerText.trim()).to.eq('Forks\n1');
75 | expect(links[3].href).to.eq('https://github.com/abraham/twitter-status/issues');
76 | expect(links[3].innerText.trim()).to.eq('Issues\n6');
77 | });
78 |
79 | it('renders clone', () => {
80 | expect(component.$('#clone pre').innerText).to.eq('git@github.com:abraham/twitter-status.git');
81 | });
82 |
83 | it('renders the footer', () => {
84 | const links = component.$$('#footer .item');
85 | expect(links.length).to.eq(3);
86 | expect(links[0].innerText).to.include('TypeScript');
87 | expect(links[1].innerText).to.include('Updated Jan 27');
88 | expect(links[2].innerText).to.include('MIT License');
89 | });
90 | });
91 |
92 | describe('with owner-repo for an empty project', () => {
93 | beforeEach(async () => {
94 | component = fixture('');
95 | await sleep(TIMEOUT);
96 | });
97 |
98 | it('renders the header', () => {
99 | const links = component.$$('#header a') as NodeListOf;
100 | expect(links.length).to.eq(3);
101 | expect(links[0].href).to.eq('https://github.com/abraham');
102 | expect(links[0].innerText).to.eq('abraham');
103 | expect(links[1].href).to.eq('https://github.com/abraham/empty');
104 | expect(links[1].innerText).to.eq('empty');
105 | expect(links[2].href).to.eq('https://github.com/abraham/empty');
106 | expect(links[2].querySelector('svg').getAttribute('aria-label')).to.eq('GitHub');
107 | });
108 |
109 | it('renders the description', () => {
110 | expect(component.$('#description').innerText).to.eq('');
111 | });
112 |
113 |
114 | it('does not render homepage', () => {
115 | expect(component.$('#homepage')).to.be.null;
116 | });
117 |
118 | it('renders the counters', () => {
119 | const links = component.$$('#counters a') as NodeListOf;
120 | expect(links.length).to.eq(4);
121 | expect(links[0].href).to.eq('https://github.com/abraham/empty/watchers');
122 | expect(links[0].innerText.trim()).to.eq('Watchers\n1');
123 | expect(links[1].href).to.eq('https://github.com/abraham/empty/stargazers');
124 | expect(links[1].innerText.trim()).to.eq('Stars\n0');
125 | expect(links[2].href).to.eq('https://github.com/abraham/empty/network');
126 | expect(links[2].innerText.trim()).to.eq('Forks\n0');
127 | expect(links[3].href).to.eq('https://github.com/abraham/empty/issues');
128 | expect(links[3].innerText.trim()).to.eq('Issues\n0');
129 | });
130 |
131 | it('renders clone', () => {
132 | expect(component.$('#clone pre').innerText).to.eq('git@github.com:abraham/empty.git');
133 | });
134 |
135 | it('renders the footer', () => {
136 | const links = component.$$('#footer .item');
137 | expect(links.length).to.eq(3);
138 | expect(links[0].innerText).to.include('Unknown language');
139 | expect(links[1].innerText).to.include('Updated Jan 28 2017');
140 | expect(links[2].innerText).to.include('Unknown license');
141 | });
142 |
143 | it('renders link decorators', () => {
144 | const linksCount = component.$$('a').length;
145 | expect(component.$$('a[target="_blank"]').length).to.eq(linksCount);
146 | expect(component.$$('a[rel="noopener"]').length).to.eq(linksCount);
147 | });
148 | });
149 |
150 | describe('GitHub API', () => {
151 | it('is requested', () => {
152 | window.fetch = sinon.spy();
153 | component = fixture('');
154 | expect((window.fetch as sinon.SinonSpy).calledWith('https://api.github.com/repos/abraham/twitter-status')).to.be.true;
155 | expect((window.fetch as sinon.SinonSpy).calledOnce).to.be.true;
156 | });
157 |
158 | describe('with error response', () => {
159 | beforeEach(async () => {
160 | stub.restore();
161 | const realFetch = window.fetch;
162 | stub = sinon.stub(window, 'fetch').callsFake(async () => {
163 | const error = await realFetch(`./base/test/data/error.json`);
164 | return new Response(await error.text(), { status: 403, statusText: 'Forbidden' })
165 | });
166 | component = fixture('');
167 | await sleep(TIMEOUT);
168 | });
169 |
170 | afterEach(() => {
171 | stub.restore();
172 | });
173 |
174 | it('renders error', () => {
175 | expect(component.$('#error')).to.exist;
176 | const text = `Error getting abraham/twitter-status details from from GitHub:
177 | "API rate limit exceeded for 71.90.116.85. (But here\'s the good news: Authenticated requests get a higher rate limit. Check out the documentation for more details.)"`;
178 | expect(component.$('#error').innerText).to.eq(text);
179 | });
180 | });
181 |
182 | describe('with recent cache', () => {
183 | beforeEach(async () => {
184 | const data = await fetch('https://api.github.com/repos/abraham/twitter-status');
185 | const cache = {
186 | data: await data.json(),
187 | cachedAt: Date.now() - (23 * 60 * 60 * 1000),
188 | };
189 | window.localStorage.setItem('github-repository_abraham/twitter-status_cache', JSON.stringify(cache));
190 | });
191 |
192 | it('is not requested', () => {
193 | window.fetch = sinon.spy();
194 | component = fixture('');
195 | expect((window.fetch as sinon.SinonSpy).calledWith('https://api.github.com/repos/abraham/twitter-status')).to.be.false;
196 | expect((window.fetch as sinon.SinonSpy).calledOnce).to.be.false;
197 | });
198 | });
199 |
200 | describe('with old cache', () => {
201 | beforeEach(async () => {
202 | const data = await fetch('https://api.github.com/repos/abraham/twitter-status');
203 | const cache = {
204 | data: await data.json(),
205 | cachedAt: Date.now() - (25 * 60 * 60 * 1000),
206 | };
207 | window.localStorage.setItem('github-repository_abraham/twitter-status_cache', JSON.stringify(cache));
208 | });
209 |
210 | it('is requested', () => {
211 | window.fetch = sinon.spy();
212 | component = fixture('');
213 | expect((window.fetch as sinon.SinonSpy).calledWith('https://api.github.com/repos/abraham/twitter-status')).to.be.true;
214 | expect((window.fetch as sinon.SinonSpy).calledOnce).to.be.true;
215 | setTimeout(() => {
216 | const cache = JSON.parse(window.localStorage.getItem('github-repository_abraham/twitter-status_cache'));
217 | expect(cache.cachedAt).to.be.within(Date.now() - 1000, Date.now() + 1000);
218 | }, TIMEOUT);
219 | });
220 | });
221 | });
222 |
223 |
224 | describe('slot', () => {
225 | beforeEach(async () => {
226 | component = fixture(`
227 |
228 |
229 |
230 |
231 |
232 | `);
233 | await sleep(TIMEOUT);
234 | });
235 |
236 | it('badges are rendered', () => {
237 | const assignedNodes = (component.$('#badges-slot slot') as HTMLSlotElement).assignedNodes();
238 | expect(assignedNodes.length).to.eq(2);
239 | expect((assignedNodes[0] as HTMLAnchorElement).href).to.eq('https://npmjs.com/package/twitter-status');
240 | });
241 |
242 | it('images are rendered', () => {
243 | const assignedNodes = (component.$('#images-slot') as HTMLSlotElement).assignedNodes();
244 | expect(assignedNodes.length).to.eq(1);
245 | expect((assignedNodes[0] as HTMLImageElement).src).to.eq('https://raw.githubusercontent.com/abraham/twitter-status/master/images/simple.png');
246 | });
247 | });
248 | });
249 |
250 | function fixture(tag: string): GithubRepository {
251 | function fixtureContainer(): HTMLElement {
252 | let div = document.createElement('div');
253 | div.classList.add('fixture');
254 | return div;
255 | }
256 | let fixture = document.body.querySelector('.fixture') || document.body.appendChild(fixtureContainer());
257 | fixture.innerHTML = tag;
258 | return fixture.children[0] as GithubRepository;
259 | }
260 |
261 | function sleep(ms: number): Promise<{}> {
262 | return new Promise(resolve => setTimeout(resolve, ms));
263 | }
264 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.production",
3 | "include": [
4 | "src",
5 | "test"
6 | ]
7 | }
8 |
--------------------------------------------------------------------------------
/tsconfig.production.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "declaration": true,
4 | "emitDecoratorMetadata": true,
5 | "experimentalDecorators": true,
6 | "inlineSources": true,
7 | "lib": ["esnext", "dom"],
8 | "module": "esnext",
9 | "moduleResolution": "node",
10 | "noFallthroughCasesInSwitch": true,
11 | "noImplicitAny": true,
12 | "noImplicitReturns": true,
13 | "noUnusedParameters": true,
14 | "outDir": "dist",
15 | "skipLibCheck": true,
16 | "sourceMap": true,
17 | "sourceRoot": "src",
18 | "strict": true,
19 | "target": "esnext"
20 | },
21 | "include": [
22 | "src"
23 | ],
24 | "exclude": [
25 | "node_modules",
26 | "dist"
27 | ]
28 | }
29 |
--------------------------------------------------------------------------------