Skip to content

Commit 2c2d1c0

Browse files
christopherthielenmergify[bot]
authored andcommittedDec 1, 2021
chore(ng13): Add helper to scaffold new tests for angular and typescript versions
1 parent b2b9ce2 commit 2c2d1c0

File tree

17 files changed

+407
-1
lines changed

17 files changed

+407
-1
lines changed
 

‎add_support_for_new_angular_version.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,12 @@ Notes from when I added Angular 11 support
88
- npx check-peer-dependencies
99
- gh pr create
1010
- update other libs
11-
- update tests in test-angular-versions/ and test-typescript-versions/
11+
- update tests in test-angular-versions/
12+
- ./scaffold.sh 11
13+
- remove old tests fro test-angular-versions and ../downstream_projects.json
14+
- update tests in test-typescript-versions/
15+
- ./scaffold.sh 4.5
16+
- (maybe) remove old tests fro test-typescript-versions and ../downstream_projects.json
1217
- npx check-peer-dependencies
1318
- gh pr create
1419
- npm run release
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
#!/usr/bin/env node
2+
const fs = require('fs');
3+
// JSON parse/stringify with support for comments (tsconfig.json can have comments)
4+
const { get, set, unset } = require('lodash');
5+
const yargs = require('yargs');
6+
7+
const configureCli = () => {
8+
const yargs = require('yargs');
9+
10+
const addDefaultPositionalArgs = (_yargs) => {
11+
_yargs.positional('filename', { description: 'The JSON file' });
12+
_yargs.positional('jsonpath', { description: 'A lodash-style JSON Path' });
13+
};
14+
15+
yargs.command(
16+
'read <filename> <jsonpath>',
17+
'Outputs a value from a JSON file at the given path',
18+
addDefaultPositionalArgs,
19+
({ filename, jsonpath }) => {
20+
console.log(readJsonField(filename, jsonpath));
21+
},
22+
);
23+
24+
yargs.command(
25+
'write <filename> <jsonpath> <value>',
26+
'Writes a value to a JSON file at the given path',
27+
(_yargs) => {
28+
addDefaultPositionalArgs(_yargs);
29+
_yargs.positional('value', {
30+
type: 'string',
31+
description: 'The new value to write',
32+
});
33+
_yargs.option('type', {
34+
description: 'writes the value as a JSON boolean/number/string',
35+
type: 'string',
36+
choices: ['boolean', 'number', 'string'],
37+
default: 'string',
38+
});
39+
},
40+
({ filename, jsonpath, value, type }) => {
41+
let newvalue = value;
42+
if (type === 'boolean') {
43+
newvalue = newvalue === 'true' ? true : newvalue === 'false' ? false : newvalue;
44+
if (typeof newvalue !== 'boolean') {
45+
throw new Error(`Cannot parse ${value} as a boolean`);
46+
}
47+
} else if (type === 'number') {
48+
const newvalue = Number(value);
49+
if (isNaN(newvalue)) {
50+
throw new Error(`Cannot parse ${value} as a number`);
51+
}
52+
}
53+
writeJsonField(filename, jsonpath, newvalue);
54+
},
55+
);
56+
57+
yargs.command(
58+
'delete <filename> <jsonpath>',
59+
'Deletes a property from a JSON file at the given path',
60+
addDefaultPositionalArgs,
61+
({ filename, jsonpath }) => {
62+
deleteJsonField(filename, jsonpath);
63+
},
64+
);
65+
66+
yargs.demandCommand(1);
67+
yargs.strictCommands();
68+
yargs.wrap(null);
69+
70+
yargs.example('read-write-json.js read package.json version', 'Outputs the version property from package.json');
71+
yargs.example(
72+
'read-write-json.js write package.json devDependencies.husky 6.0.0',
73+
'Writes "husky": "6.0.0" to the "devDependencies" property of package.json',
74+
);
75+
yargs.example(
76+
'read-write-json.js delete package.json devDependencies.husky',
77+
'Deletes the "husky" key from the "devDependencies" property of package.json',
78+
);
79+
yargs.parse();
80+
};
81+
82+
if (require.main === module) {
83+
configureCli();
84+
}
85+
86+
function readJson(filename) {
87+
const string = fs.readFileSync(filename, 'utf-8');
88+
return JSON.parse(string);
89+
}
90+
91+
function writeJson(filename, json) {
92+
const data = JSON.stringify(json, null, 2);
93+
fs.writeFileSync(filename, data, 'utf-8');
94+
}
95+
96+
function readJsonField(filename, path) {
97+
const json = readJson(filename);
98+
return get(json, path);
99+
}
100+
101+
function deleteJsonField(filename, field) {
102+
const json = readJson(filename);
103+
unset(json, field);
104+
writeJson(filename, json);
105+
}
106+
107+
function writeJsonField(filename, field, val) {
108+
const json = readJson(filename);
109+
set(json, field, val);
110+
writeJson(filename, json);
111+
}
112+
113+
module.exports.readJson = readJson;
114+
module.exports.writeJson = writeJson;
115+
module.exports.readJsonField = readJsonField;
116+
module.exports.writeJsonField = writeJsonField;
117+
module.exports.deleteJsonField = deleteJsonField;

‎test-angular-versions/scaffold.sh

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#!/usr/bin/env bash
2+
3+
VERSION=$1;
4+
if [[ "x" == "x$VERSION" ]] ; then
5+
echo "specify the version of Angular to test. e.g., to test Angular v14:"
6+
echo "$0 14"
7+
exit 1;
8+
fi
9+
10+
JSON=./read-write-json.js
11+
DIR=v$VERSION
12+
13+
npx -y -p @angular/cli@$VERSION ng new --package-manager=yarn --style=css --routing=false --skip-git --skip-install --skip-tests $DIR
14+
rm -rf $DIR/src/app
15+
cp -Rp scaffold/* $DIR
16+
17+
$JSON write $DIR/package.json name "$VERSION"
18+
$JSON write $DIR/package.json dependencies.@uirouter/angular "*"
19+
$JSON write $DIR/package.json dependencies.@uirouter/cypress-runner "*"
20+
$JSON write $DIR/package.json scripts.test "npm run test:dev && npm run test:prod"
21+
$JSON write $DIR/package.json scripts.test:dev "ng build --configuration development && cypress-runner run --path dist/$DIR"
22+
$JSON write $DIR/package.json scripts.test:prod "ng build --configuration production && cypress-runner run --path dist/$DIR"
23+
24+
$JSON write ../downstream_projects.json "projects.angular$VERSION" "./test-angular-versions/$DIR"
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"baseUrl": "http://localhost:4000",
3+
"video": false
4+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
describe('Angular app', () => {
2+
beforeEach(() => {
3+
window.sessionStorage.clear();
4+
});
5+
6+
it('loads', () => {
7+
cy.visit('');
8+
});
9+
10+
it('loads home state by default', () => {
11+
cy.visit('');
12+
cy.url().should('include', '/home');
13+
});
14+
15+
it('renders uisref as links', () => {
16+
cy.visit('');
17+
cy.get('a').contains('home');
18+
cy.get('a').contains('about');
19+
cy.get('a').contains('lazy');
20+
cy.get('a').contains('lazy.child');
21+
cy.get('a').contains('lazy.child.viewtarget');
22+
});
23+
24+
it('renders home', () => {
25+
cy.visit('/home');
26+
cy.get('a').contains('home').should('have.class', 'active');
27+
cy.get('a').contains('about').should('not.have.class', 'active');
28+
cy.get('#default').contains('home works');
29+
});
30+
31+
it('renders about', () => {
32+
cy.visit('/home');
33+
cy.visit('/about');
34+
cy.get('a').contains('home').should('not.have.class', 'active');
35+
cy.get('a').contains('about').should('have.class', 'active');
36+
cy.get('#default').contains('about works');
37+
});
38+
39+
it('loads lazy routes', () => {
40+
cy.visit('/home');
41+
cy.visit('/lazy');
42+
cy.get('a').contains('home').should('not.have.class', 'active');
43+
cy.get('a').contains('lazy').should('have.class', 'active');
44+
cy.get('#default').contains('lazy works');
45+
});
46+
47+
it('routes to lazy routes', () => {
48+
cy.visit('/lazy');
49+
cy.get('a').contains('home').should('not.have.class', 'active');
50+
cy.get('a').contains('lazy').should('have.class', 'active');
51+
cy.get('#default').contains('lazy works');
52+
});
53+
54+
it('routes to lazy child routes', () => {
55+
cy.visit('/lazy/child');
56+
cy.get('a').contains('home').should('not.have.class', 'active');
57+
cy.get('a').contains('lazy.child').should('have.class', 'active');
58+
cy.get('#default').contains('lazy.child works');
59+
});
60+
61+
it('targets named views', () => {
62+
cy.visit('/lazy/child/viewtarget');
63+
cy.get('a').contains('home').should('not.have.class', 'active');
64+
cy.get('a').contains('lazy.child').should('have.class', 'active');
65+
cy.get('#default').contains('lazy.child works');
66+
cy.get('#header').contains('lazy.child.viewtarget works');
67+
cy.get('#footer').contains('lazy.child.viewtarget works');
68+
});
69+
});
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { Component } from '@angular/core';
2+
3+
@Component({
4+
selector: 'app-about',
5+
template: ` <p>about works!</p> `,
6+
})
7+
export class AboutComponent {}

‎test-angular-versions/scaffold/src/app/app.component.css

Whitespace-only changes.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<!--The content below is only a placeholder and can be replaced.-->
2+
<div style="text-align: center">
3+
<h1>Welcome to {{ title }}!</h1>
4+
<img
5+
width="300"
6+
alt="Angular Logo"
7+
src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTAgMjUwIj4KICAgIDxwYXRoIGZpbGw9IiNERDAwMzEiIGQ9Ik0xMjUgMzBMMzEuOSA2My4ybDE0LjIgMTIzLjFMMTI1IDIzMGw3OC45LTQzLjcgMTQuMi0xMjMuMXoiIC8+CiAgICA8cGF0aCBmaWxsPSIjQzMwMDJGIiBkPSJNMTI1IDMwdjIyLjItLjFWMjMwbDc4LjktNDMuNyAxNC4yLTEyMy4xTDEyNSAzMHoiIC8+CiAgICA8cGF0aCAgZmlsbD0iI0ZGRkZGRiIgZD0iTTEyNSA1Mi4xTDY2LjggMTgyLjZoMjEuN2wxMS43LTI5LjJoNDkuNGwxMS43IDI5LjJIMTgzTDEyNSA1Mi4xem0xNyA4My4zaC0zNGwxNy00MC45IDE3IDQwLjl6IiAvPgogIDwvc3ZnPg=="
8+
/>
9+
</div>
10+
<h2>Here are some links to help you start:</h2>
11+
<ul>
12+
<li>
13+
<h2><a target="_blank" rel="noopener" href="https://angular.io/tutorial">Tour of Heroes</a></h2>
14+
</li>
15+
<li>
16+
<h2><a target="_blank" rel="noopener" href="https://angular.io/cli">CLI Documentation</a></h2>
17+
</li>
18+
<li>
19+
<h2><a target="_blank" rel="noopener" href="https://blog.angular.io/">Angular blog</a></h2>
20+
</li>
21+
</ul>
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { Component } from '@angular/core';
2+
3+
const template = `
4+
<ui-view name="header" id="header"></ui-view>
5+
6+
<div class="app">
7+
<img width="300" alt="Angular Logo" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTAgMjUwIj4KICAgIDxwYXRoIGZpbGw9IiNERDAwMzEiIGQ9Ik0xMjUgMzBMMzEuOSA2My4ybDE0LjIgMTIzLjFMMTI1IDIzMGw3OC45LTQzLjcgMTQuMi0xMjMuMXoiIC8+CiAgICA8cGF0aCBmaWxsPSIjQzMwMDJGIiBkPSJNMTI1IDMwdjIyLjItLjFWMjMwbDc4LjktNDMuNyAxNC4yLTEyMy4xTDEyNSAzMHoiIC8+CiAgICA8cGF0aCAgZmlsbD0iI0ZGRkZGRiIgZD0iTTEyNSA1Mi4xTDY2LjggMTgyLjZoMjEuN2wxMS43LTI5LjJoNDkuNGwxMS43IDI5LjJIMTgzTDEyNSA1Mi4xem0xNyA4My4zaC0zNGwxNy00MC45IDE3IDQwLjl6IiAvPgogIDwvc3ZnPg==">
8+
9+
<div>
10+
11+
<a uiSref="home" uiSrefActive="active">home</a>
12+
<a uiSref="about" uiSrefActive="active">about</a>
13+
<a uiSref="lazy" uiSrefActiveEq="active">lazy</a>
14+
<a uiSref="lazy.child" uiSrefActive="active">lazy.child</a>
15+
<a uiSref="lazy.child.viewtarget" uiSrefActive="active">lazy.child.viewtarget</a>
16+
</div>
17+
18+
<ui-view id="default"></ui-view>
19+
</div>
20+
21+
<ui-view name="footer" id="footer"></ui-view>
22+
`;
23+
24+
@Component({
25+
selector: 'app-root',
26+
template: template,
27+
styles: [
28+
`
29+
.app {
30+
text-align: center;
31+
border: 1px solid;
32+
}
33+
34+
.active {
35+
font-weight: bold;
36+
}
37+
`,
38+
],
39+
})
40+
export class AppComponent {}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { BrowserModule } from '@angular/platform-browser';
2+
import { NgModule } from '@angular/core';
3+
import { UIRouterModule } from '@uirouter/angular';
4+
import { UIRouter } from '@uirouter/core';
5+
6+
import { AppComponent } from './app.component';
7+
import { HomeComponent } from './home.component';
8+
import { AboutComponent } from './about.component';
9+
10+
export const states = [
11+
{ name: 'home', url: '/home', component: HomeComponent },
12+
{ name: 'about', url: '/about', component: AboutComponent },
13+
{ name: 'lazy.**', url: '/lazy', loadChildren: () => import('./lazy/lazy.module').then((m) => m.LazyModule) },
14+
];
15+
16+
export function config(router: UIRouter) {
17+
router.urlService.rules.initial({ state: 'home' });
18+
}
19+
20+
@NgModule({
21+
imports: [BrowserModule, UIRouterModule.forRoot({ states, config })],
22+
declarations: [AppComponent, HomeComponent, AboutComponent],
23+
bootstrap: [AppComponent],
24+
})
25+
export class AppModule {}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { Component } from '@angular/core';
2+
3+
@Component({
4+
selector: 'app-home',
5+
template: ` <p>home works!</p> `,
6+
})
7+
export class HomeComponent {}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { Component, Input } from '@angular/core';
2+
3+
@Component({
4+
selector: 'app-lazy',
5+
template: `
6+
<p>{{ state.name }} works!</p>
7+
<ui-view></ui-view>
8+
`,
9+
})
10+
export class LazyComponent {
11+
@Input('$state$') state: any;
12+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { NgModule } from '@angular/core';
2+
import { CommonModule } from '@angular/common';
3+
import { UIRouterModule } from '@uirouter/angular';
4+
import { LazyComponent } from './lazy.component';
5+
6+
export const states = [
7+
{ name: 'lazy', url: '/lazy', component: LazyComponent },
8+
{ name: 'lazy.child', url: '/child', component: LazyComponent },
9+
{
10+
name: 'lazy.child.viewtarget',
11+
url: '/viewtarget',
12+
views: {
13+
'!header': { component: LazyComponent },
14+
'footer@': { component: LazyComponent },
15+
},
16+
},
17+
];
18+
19+
@NgModule({
20+
imports: [CommonModule, UIRouterModule.forChild({ states: states })],
21+
declarations: [LazyComponent],
22+
})
23+
export class LazyModule {}

‎test-typescript-versions/scaffold.sh

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#!/usr/bin/env bash
2+
3+
JSON="../test-angular-versions/read-write-json.js"
4+
VERSION=$1;
5+
if [[ "x" == "x$VERSION" ]] ; then
6+
echo "specify the version of Typescript to test. e.g., to test Typescript 4.7:"
7+
echo "$0 4.7"
8+
exit 1;
9+
fi
10+
11+
DIR=typescript$VERSION
12+
13+
mkdir $DIR
14+
cp -Rp scaffold/* $DIR
15+
16+
$JSON write $DIR/package.json name "@uirouter/angular-test-typescript$VERSION"
17+
$JSON write $DIR/package.json description "Test against Typescript $VERSION"
18+
$JSON write $DIR/package.json dependencies.typescript "$VERSION"
19+
20+
$JSON write ../downstream_projects.json "projects.typescript$(echo $VERSION | sed -e 's/\.//g')" "./test-typescript-versions/$DIR"
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import { UIRouter } from '@uirouter/angular';
2+
console.log(UIRouter); // tslint:disable-line:no-console

0 commit comments

Comments
 (0)