Skip to content

Commit

Permalink
use screenshot test to capture scenes for components (angular#766)
Browse files Browse the repository at this point in the history
Co-authored-by: Annie Wang <[email protected]>
  • Loading branch information
annieyw and annieyw authored Jun 2, 2020
1 parent 33b6d77 commit 323f126
Show file tree
Hide file tree
Showing 28 changed files with 635 additions and 0 deletions.
122 changes: 122 additions & 0 deletions angular.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"defaultProject": "material-angular-io",
"projects": {
"material-angular-io": {
"root": "",
Expand Down Expand Up @@ -198,6 +199,127 @@
}
}
}
},
"scenes": {
"projectType": "application",
"schematics": {
"@schematics/angular:component": {
"style": "scss"
}
},
"root": "scenes",
"sourceRoot": "scenes/src",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/scenes",
"index": "scenes/src/index.html",
"main": "scenes/src/main.ts",
"polyfills": "scenes/src/polyfills.ts",
"tsConfig": "scenes/tsconfig.app.json",
"aot": true,
"assets": [
"scenes/src/favicon.ico",
"scenes/src/assets"
],
"styles": [
"scenes/src/styles.scss"
],
"scripts": []
},
"configurations": {
"production": {
"fileReplacements": [
{
"replace": "scenes/src/environments/environment.ts",
"with": "scenes/src/environments/environment.prod.ts"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"extractCss": true,
"namedChunks": false,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"budgets": [
{
"type": "initial",
"maximumWarning": "2mb",
"maximumError": "5mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "6kb",
"maximumError": "10kb"
}
]
}
}
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "scenes:build"
},
"configurations": {
"production": {
"browserTarget": "scenes:build:production"
}
}
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "scenes:build"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "scenes/src/test.ts",
"polyfills": "scenes/src/polyfills.ts",
"tsConfig": "scenes/tsconfig.spec.json",
"karmaConfig": "scenes/karma.conf.js",
"assets": [
"scenes/src/favicon.ico",
"scenes/src/assets"
],
"styles": [
"scenes/src/styles.scss"
],
"scripts": []
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"scenes/tsconfig.app.json",
"scenes/tsconfig.spec.json",
"scenes/e2e/tsconfig.json"
],
"exclude": [
"**/node_modules/**"
]
}
},
"e2e": {
"builder": "@angular-devkit/build-angular:protractor",
"options": {
"protractorConfig": "scenes/e2e/protractor.conf.js",
"devServerTarget": "scenes:serve"
},
"configurations": {
"production": {
"devServerTarget": "scenes:serve:production"
}
}
}
}
}
},
"cli": {
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@
"start": "ng serve",
"start:jit": "ng serve --aot=false",
"start:prod": "ng serve --prod",
"start:scenes": "ng serve scenes",
"lint": "ng lint",
"test": "ng test",
"pree2e": "webdriver-manager update",
"e2e": "ng e2e",
"generate-scenes": "ng e2e scenes",
"build": "ng build",
"build:content": "yarn upgrade @angular/components-examples",
"build:sm": "ng build --prod --source-map",
Expand Down
12 changes: 12 additions & 0 deletions scenes/browserslist
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
# For additional information regarding the format and rule options, please see:
# https://github.com/browserslist/browserslist#queries

# You can see what browsers were selected by your queries by running:
# npx browserslist

> 0.5%
last 2 versions
Firefox ESR
not dead
not IE 9-11 # For IE 9-11 support, remove 'not'.
32 changes: 32 additions & 0 deletions scenes/e2e/protractor.conf.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// @ts-check
// Protractor configuration file, see link for more information
// https://github.com/angular/protractor/blob/master/lib/config.ts

const { SpecReporter } = require('jasmine-spec-reporter');

/**
* @type { import("protractor").Config }
*/
exports.config = {
allScriptsTimeout: 11000,
specs: [
'./src/**/*.e2e-spec.ts'
],
capabilities: {
browserName: 'chrome'
},
directConnect: true,
baseUrl: 'http://localhost:4200/',
framework: 'jasmine',
jasmineNodeOpts: {
showColors: true,
defaultTimeoutInterval: 30000,
print: function() {}
},
onPrepare() {
require('ts-node').register({
project: require('path').join(__dirname, './tsconfig.json')
});
jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
}
};
45 changes: 45 additions & 0 deletions scenes/e2e/screenshot.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import * as fs from 'fs';
import * as path from 'path';
import {by, element} from 'protractor';

const OUTPUT_DIR = path.join(__dirname, '..', '..', 'src', 'assets', 'screenshots');


export class Screenshot {
/** The filename used to store the screenshot. */
get filename(): string {
return this.id
.toLowerCase()
.replace(/\s/g, '_')
.replace(/[^/a-z0-9_-]+/g, '')
+ '.scene.png';
}

/** The full path to the screenshot */
get fullPath(): string {
return path.resolve(OUTPUT_DIR, this.filename);
}

constructor(readonly id: string) {}

async takeScreenshot() {
const png = await element(by.tagName('app-scene-viewer')).takeScreenshot();
this.storeScreenshot(png);
}

/** Replaces the existing screenshot with the newly generated one. */
storeScreenshot(png: string) {
if (!fs.existsSync(OUTPUT_DIR)) {
fs.mkdirSync(OUTPUT_DIR, '444');
}

if (fs.existsSync(OUTPUT_DIR)) {
fs.writeFileSync(this.fullPath, png, {encoding: 'base64' });
}
}
}

export function screenshot(id: string): Promise<void> {
const s = new Screenshot(id);
return s.takeScreenshot();
}
11 changes: 11 additions & 0 deletions scenes/e2e/src/app.e2e-spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import {AppPage} from './app.po';

describe('screenshot scenes for each component', () => {
// These tests simply serve as a convenient way to take snapshots of different pages,
// they are not actually testing anything
let page: AppPage;

beforeEach(() => {
page = new AppPage();
});
});
7 changes: 7 additions & 0 deletions scenes/e2e/src/app.po.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { browser } from 'protractor';

export class AppPage {
async navigateTo(component: string): Promise<unknown> {
return browser.get(browser.baseUrl + '/' + component);
}
}
13 changes: 13 additions & 0 deletions scenes/e2e/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "../../../out-tsc/e2e",
"module": "commonjs",
"target": "es5",
"types": [
"jasmine",
"jasminewd2",
"node"
]
}
}
32 changes: 32 additions & 0 deletions scenes/karma.conf.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Karma configuration file, see link for more information
// https://karma-runner.github.io/1.0/config/configuration-file.html

module.exports = function (config) {
config.set({
basePath: '',
frameworks: ['jasmine', '@angular-devkit/build-angular'],
plugins: [
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('karma-coverage-istanbul-reporter'),
require('@angular-devkit/build-angular/plugins/karma')
],
client: {
clearContext: false // leave Jasmine Spec Runner output visible in browser
},
coverageIstanbulReporter: {
dir: require('path').join(__dirname, '../../coverage/scenes'),
reports: ['html', 'lcovonly', 'text-summary'],
fixWebpackSourcePaths: true
},
reporters: ['progress', 'kjhtml'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
singleRun: false,
restartOnFileChange: true
});
};
11 changes: 11 additions & 0 deletions scenes/src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';


const routes: Routes = [];

@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
Empty file.
22 changes: 22 additions & 0 deletions scenes/src/app/app.component.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { TestBed, async } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { AppComponent } from './app.component';

describe('AppComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
RouterTestingModule
],
declarations: [
AppComponent
],
}).compileComponents();
}));

it('should create the app', () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.componentInstance;
expect(app).toBeTruthy();
});
});
8 changes: 8 additions & 0 deletions scenes/src/app/app.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { Component } from '@angular/core';

@Component({
selector: 'app-root',
template: '<router-outlet></router-outlet>',
styleUrls: ['./app.component.scss']
})
export class AppComponent { }
28 changes: 28 additions & 0 deletions scenes/src/app/app.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import {BrowserModule} from '@angular/platform-browser';
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
import {NgModule} from '@angular/core';

import {AppRoutingModule} from './app-routing.module';
import {AppComponent} from './app.component';
import {MatNativeDateModule} from '@angular/material/core';
import {MatDialogModule} from '@angular/material/dialog';
import {MatDatepickerModule} from '@angular/material/datepicker';
import {ScrollingModule} from '@angular/cdk/scrolling';

@NgModule({
declarations: [
AppComponent
],
imports: [
MatDatepickerModule,
BrowserModule,
AppRoutingModule,
BrowserAnimationsModule,
MatNativeDateModule,
MatDialogModule,
ScrollingModule
],
bootstrap: [AppComponent]
})
export class AppModule {
}
1 change: 1 addition & 0 deletions scenes/src/app/scene-viewer/scene-viewer.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<ng-template #scene></ng-template>
6 changes: 6 additions & 0 deletions scenes/src/app/scene-viewer/scene-viewer.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
app-scene-viewer {
display: block;
width: 480px;
height: 300px;
background-color: #fff2f4;
}
Loading

0 comments on commit 323f126

Please sign in to comment.