Skip to content

Commit 27c5031

Browse files
authored
Create pipeline that will automatically check for Accessibility Issues (#1584)
* Create mainCI.yml Work in progress, don't merge * Update mainCI.yml * Update mainCI.yml * Update mainCI.yml * Update mainCI.yml * Update mainCI.yml * added script for build website * Update mainCI.yml * Update mainCI.yml * Update mainCI.yml * Update mainCI.yml * Update mainCI.yml * Update mainCI.yml * Update mainCI.yml * Fixed color contrast accessibility issues * Fixed ari-roles issues * added static storage wip * Added missing static data * Update mainCI.yml * added static data for requests made at publishing time * updated PublisherStaticDataProvider * updated PublisherStaticDataProvider * updated PublisherStaticDataProvider * get data from default.json too * added build-static-data script * refactoring * removed logs * removed some headers from static data * removed headers * added smaller GraphQL api * Update mainCI.yml * Update mainCI.yml * Update mainCI.yml * Update mainCI.yml * test accessibility on profile * Update mainCI.yml * Update mainCI.yml * removed headers * test with pre-populated e-mail and password * compacted json files * removed test e-mail and password * code review changes * test for signed in version * added default.json and defaultMockData.json only for staticData * fixed webpack configs * fixed accessibility issues * fixed accessibility issues * added staticDataEnviroment constant * Update mainCI.yml * removed logs * renamed defaultMockData.json
1 parent f916f32 commit 27c5031

18 files changed

+326
-70
lines changed

.github/workflows/mainCI.yml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
name: CI
2+
3+
on:
4+
pull_request:
5+
branches:
6+
- master
7+
8+
jobs:
9+
build:
10+
runs-on: ubuntu-latest
11+
12+
steps:
13+
- name: Use Node.js 16.x
14+
uses: actions/checkout@v2
15+
with:
16+
node-version: 16.x
17+
18+
- name: Install
19+
run: npm install
20+
21+
- name: Build
22+
run: npm run build-static-data
23+
24+
- name: Scan for accessibility issues
25+
uses: microsoft/accessibility-insights-action@v2
26+
with:
27+
repo-token: ${{ secrets.GITHUB_TOKEN }}
28+
site-dir: ${{ github.workspace }}/dist/website
29+
localhost-port: 12345
30+
input-urls: http://localhost:12345/profile http://localhost:12345/500 http://localhost:12345/404
31+
32+
- name: Upload report artifact
33+
uses: actions/upload-artifact@v2
34+
with:
35+
name: accessibility-reports
36+
path: ${{ github.workspace }}/_accessibility-reports

environmentConstants.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
2+
const staticDataEnvironment = "staticData";
3+
4+
module.exports = {
5+
staticDataEnvironment
6+
}

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@
2020
"test": "node node_modules/mocha/bin/_mocha -r mocha.js src/**/*.spec.ts tests/e2e/**/*.spec.ts --timeout 30000",
2121
"deploy-function": "npm run build-function && cd dist/function && func azure functionapp publish < function app name >",
2222
"publish": "webpack --config webpack.publisher.js && node dist/publisher/index.js && npm run serve-website",
23-
"serve-website": "webpack serve --open --static ./dist/website --no-stats"
23+
"serve-website": "webpack serve --open --static ./dist/website --no-stats",
24+
"build-static-data": "webpack --config webpack.staticData.js && node dist/publisher/index.js"
2425
},
2526
"devDependencies": {
2627
"@azure/storage-blob": "12.8.0",

src/apim.publish.module.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ import { ApiProductsModule } from "./components/apis/api-products/ko/apiProducts
3737
import { RuntimeConfigPublisher } from "./publishing/runtimeConfigPublisher";
3838
import { RuntimeConfigBuilder } from "./publishing/runtimeConfigBuilder";
3939
import { CustomHtmlPublishModule } from "./components/custom-html/customHtml.publish.module";
40+
import { StaticDataHttpClient } from "./services/staticDataHttpClient";
41+
import { PublisherStaticDataProvider } from "./services/publisherStaticDataProvider";
42+
import {staticDataEnvironment} from "./../environmentConstants"
4043

4144
export class ApimPublishModule implements IInjectorModule {
4245
public register(injector: IInjector): void {
@@ -63,7 +66,7 @@ export class ApimPublishModule implements IInjectorModule {
6366
injector.bindModule(new ReportsModule());
6467
injector.bindModule(new ValidationSummaryModule());
6568
injector.bindModule(new CustomHtmlPublishModule());
66-
injector.bindSingleton("tenantService", TenantService);
69+
injector.bindSingleton("tenantService", TenantService);
6770
injector.bindSingleton("backendService", BackendService);
6871
injector.bindSingleton("userService", StaticUserService);
6972
injector.bindSingleton("roleService", StaticRoleService);
@@ -80,6 +83,11 @@ export class ApimPublishModule implements IInjectorModule {
8083
injector.bindSingleton("runtimeConfigBuilder", RuntimeConfigBuilder);
8184
injector.bindToCollection("publishers", AadConfigPublisher);
8285
injector.bindToCollection("publishers", RuntimeConfigPublisher);
83-
86+
87+
if (process.env.NODE_ENV === staticDataEnvironment) {
88+
injector.bind("httpClient", StaticDataHttpClient);
89+
injector.bind("dataProvider", PublisherStaticDataProvider);
90+
}
91+
8492
}
8593
}

src/apim.runtime.module.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,10 @@ import { UsersService } from "./services/usersService";
7777
import { ApimSettingsProvider } from "./configuration/apimSettingsProvider";
7878
import { AccessTokenRefrsher } from "./authentication/accessTokenRefresher";
7979
import { Pagination } from "./components/pagination/pagination";
80+
import { StaticDataHttpClient } from "./services/staticDataHttpClient";
8081
import { OauthServerConfiguration } from "./components/operations/operation-details/ko/runtime/oauth-server-configuration";
82+
import { RuntimeStaticDataProvider } from "./services/runtimeStaticDataProvider";
83+
import {staticDataEnvironment} from "./../environmentConstants"
8184

8285

8386
export class ApimRuntimeModule implements IInjectorModule {
@@ -149,5 +152,10 @@ export class ApimRuntimeModule implements IInjectorModule {
149152
injector.bindToCollection("autostart", AccessTokenRefrsher);
150153
injector.bind("pagination", Pagination);
151154
injector.bind("oauthServerConfiguration", OauthServerConfiguration);
155+
156+
if (process.env.NODE_ENV === staticDataEnvironment) {
157+
injector.bind("httpClient", StaticDataHttpClient);
158+
injector.bind("dataProvider", RuntimeStaticDataProvider);
159+
}
152160
}
153161
}
Lines changed: 41 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<div class="form-group">
2-
<div class="input-group" tabindex="0" role="button" aria-label="APIs">
2+
<div class="input-group" tabindex="0" aria-label="APIs">
33
<div class="form-control" data-toggle="dropdown">
44
<span data-bind="text: selection"></span>
55
<!-- ko if: selectedApi() -->
@@ -14,59 +14,59 @@
1414
<!-- /ko -->
1515
<!-- /ko -->
1616
</div>
17-
<button class="input-group-addon no-border" data-toggle="dropdown">
17+
<button class="input-group-addon no-border" data-toggle="dropdown" aria-label="Expand APIs list">
1818
<i class="icon-emb icon-emb-chevron-down"></i>
1919
</button>
2020
<div class="dropdown">
2121
<input type="search" class="form-control form-control-light" aria-label="Search" placeholder="Search APIs"
2222
data-bind="textInput: pattern" autofocus />
2323

2424
<!-- <tag-input params="{ scope: 'apis', onChange: onTagsChange }"></tag-input> -->
25-
26-
<!-- ko if: working -->
27-
<spinner class="block" role="presentation"></spinner>
28-
<!-- /ko -->
2925

30-
<!-- ko ifnot: working -->
31-
<!-- ko foreach: { data: apiGroups, as: 'group' } -->
32-
<div class="tag-group">
33-
<span class="tag-item" role="group" data-bind="text: group.tag"></span>
34-
</div>
35-
<div class="menu menu-vertical" role="list">
36-
<!-- ko foreach: { data: group.items, as: 'item' } -->
37-
<a href="#" role="listitem" class="nav-link text-truncate" data-dismiss
38-
data-bind="attr: { href: $component.getReferenceUrl(item) }, css: { 'nav-link-active': $component.selectedApiName() === item.name }">
39-
<span data-bind="text: item.displayName"></span>
40-
<!-- ko if: item.type === 'soap' -->
41-
<span class="badge badge-soap">SOAP</span>
42-
<!-- /ko -->
43-
<!-- ko if: item.type === 'websocket' -->
44-
<span class="badge badge-soap">WebSocket</span>
45-
<!-- /ko -->
46-
<!-- ko if: item.type === 'graphql' -->
47-
<span class="badge badge-soap">GraphQL</span>
48-
<!-- /ko -->
49-
<!-- ko if: item.apiVersion -->
50-
- <span data-bind="text: item.apiVersion"></span>
51-
<!-- /ko -->
52-
</a>
26+
<!-- ko if: working -->
27+
<spinner class="block" role="presentation"></spinner>
28+
<!-- /ko -->
29+
30+
<!-- ko ifnot: working -->
31+
<!-- ko foreach: { data: apiGroups, as: 'group' } -->
32+
<div class="tag-group">
33+
<span class="tag-item" role="group" data-bind="text: group.tag"></span>
34+
</div>
35+
<div class="menu menu-vertical" role="list">
36+
<!-- ko foreach: { data: group.items, as: 'item' } -->
37+
<a href="#" role="listitem" class="nav-link text-truncate" data-dismiss
38+
data-bind="attr: { href: $component.getReferenceUrl(item) }, css: { 'nav-link-active': $component.selectedApiName() === item.name }">
39+
<span data-bind="text: item.displayName"></span>
40+
<!-- ko if: item.type === 'soap' -->
41+
<span class="badge badge-soap">SOAP</span>
42+
<!-- /ko -->
43+
<!-- ko if: item.type === 'websocket' -->
44+
<span class="badge badge-soap">WebSocket</span>
5345
<!-- /ko -->
54-
</div>
46+
<!-- ko if: item.type === 'graphql' -->
47+
<span class="badge badge-soap">GraphQL</span>
48+
<!-- /ko -->
49+
<!-- ko if: item.apiVersion -->
50+
- <span data-bind="text: item.apiVersion"></span>
51+
<!-- /ko -->
52+
</a>
5553
<!-- /ko -->
54+
</div>
55+
<!-- /ko -->
5656

57-
<!-- ko if: apiGroups().length === 0 -->
58-
<div class="list-item-empty">No APIs found</div>
59-
<!-- /ko -->
57+
<!-- ko if: apiGroups().length === 0 -->
58+
<div class="list-item-empty">No APIs found</div>
59+
<!-- /ko -->
6060

61-
<!-- ko ifnot: working -->
62-
<!-- ko if: $component.totalPages() > 1 -->
63-
<pagination params="{ pageNumber: $component.pageNumber, totalPages: $component.totalPages }">
64-
</pagination>
65-
<!-- /ko -->
66-
<!-- /ko -->
61+
<!-- ko ifnot: working -->
62+
<!-- ko if: $component.totalPages() > 1 -->
63+
<pagination params="{ pageNumber: $component.pageNumber, totalPages: $component.totalPages }">
64+
</pagination>
65+
<!-- /ko -->
66+
<!-- /ko -->
67+
68+
<!-- /ko -->
6769

68-
<!-- /ko -->
69-
7070
</div>
7171
</div>
7272
</div>

src/components/operations/operation-details/ko/runtime/oauth-server-configuration.html

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@
99
<div class="col-6 align-self-center">
1010
<div class="form-group">
1111
<div class="input-group">
12-
<input autocomplete="off" class="form-control form-control-sm" placeholder="value"
13-
spellcheck="false" aria-label="Supported grant flows" readonly
14-
data-bind="textInput: $component.displayedGrantFlows()">
15-
<button class="input-group-addon no-border" data-bind="copyToClipboard: $component.displayedGrantFlows()">
12+
<input autocomplete="off" class="form-control form-control-sm" placeholder="value" spellcheck="false"
13+
aria-label="Supported grant flows" readonly data-bind="textInput: $component.displayedGrantFlows()">
14+
<button class="input-group-addon no-border"
15+
data-bind="copyToClipboard: $component.displayedGrantFlows()" aria-label="Copy to clipboard">
1616
<i class="icon-emb icon-emb-duplicate"></i>
1717
</button>
1818
</div>
@@ -31,9 +31,10 @@
3131
<div class="col-6 align-self-center">
3232
<div class="form-group">
3333
<div class="input-group" data-bind="with: $component.authorizationServer">
34-
<input autocomplete="off" class="form-control form-control-sm" placeholder="value"
35-
spellcheck="false" aria-label="Client id" readonly data-bind="textInput: clientId">
36-
<button class="input-group-addon no-border" data-bind="copyToClipboard: clientId">
34+
<input autocomplete="off" class="form-control form-control-sm" placeholder="value" spellcheck="false"
35+
aria-label="Client id" readonly data-bind="textInput: clientId">
36+
<button class="input-group-addon no-border" data-bind="copyToClipboard: clientId"
37+
aria-label="Copy to clipboard">
3738
<i class="icon-emb icon-emb-duplicate"></i>
3839
</button>
3940
</div>
@@ -57,7 +58,8 @@
5758
data-bind="textInput: $component.authorizationServer().authorizationEndpoint">
5859

5960
<button class="input-group-addon no-border"
60-
data-bind="copyToClipboard: $component.authorizationServer().authorizationEndpoint">
61+
data-bind="copyToClipboard: $component.authorizationServer().authorizationEndpoint"
62+
aria-label="Copy to clipboard">
6163
<i class="icon-emb icon-emb-duplicate"></i>
6264
</button>
6365
</div>
@@ -76,11 +78,12 @@
7678
<div class="col-6 align-self-center">
7779
<div class="form-group">
7880
<div class="input-group">
79-
<input autocomplete="off" class="form-control form-control-sm" placeholder="value"
80-
spellcheck="false" aria-label="Token endpoint" readonly
81+
<input autocomplete="off" class="form-control form-control-sm" placeholder="value" spellcheck="false"
82+
aria-label="Token endpoint" readonly
8183
data-bind="textInput: $component.authorizationServer().tokenEndpoint">
8284
<button class="input-group-addon no-border"
83-
data-bind="copyToClipboard: $component.authorizationServer().tokenEndpoint">
85+
data-bind="copyToClipboard: $component.authorizationServer().tokenEndpoint"
86+
aria-label="Copy to clipboard">
8487
<i class="icon-emb icon-emb-duplicate"></i>
8588
</button>
8689
</div>
@@ -99,10 +102,10 @@
99102
<div class="col-6 align-self-center">
100103
<div class="form-group">
101104
<div class="input-group">
102-
<input autocomplete="off" class="form-control form-control-sm" placeholder="value"
103-
spellcheck="false" aria-label="Scopes" readonly
104-
data-bind="textInput: $component.displayedScopes">
105-
<button class="input-group-addon no-border" data-bind="copyToClipboard: $component.displayedScopes">
105+
<input autocomplete="off" class="form-control form-control-sm" placeholder="value" spellcheck="false"
106+
aria-label="Scopes" readonly data-bind="textInput: $component.displayedScopes">
107+
<button class="input-group-addon no-border" data-bind="copyToClipboard: $component.displayedScopes"
108+
aria-label="Copy to clipboard">
106109
<i class="icon-emb icon-emb-duplicate"></i>
107110
</button>
108111
</div>

src/components/products/product-list/ko/runtime/product-list-dropdown.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<div class="form-control" tabindex="0" role="button" aria-label="Products" data-toggle="dropdown">
44
<span data-bind="text: selection"></span>
55
</div>
6-
<button class="input-group-addon no-border" data-toggle="dropdown">
6+
<button class="input-group-addon no-border" data-toggle="dropdown" aria-label="Expand products list">
77
<i class="icon-emb icon-emb-chevron-down"></i>
88
</button>
99
<div class="dropdown">

src/components/users/profile/ko/runtime/profile.html

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121
<div class="row">
2222
<div class="col-md-12">
2323
<button type="button" class="button button-default" data-bind="click: toggleEdit">Change name</button>
24-
<button type="button" class="button button-default" data-bind="click: toggleEditPassword">Change password</button>
24+
<button type="button" class="button button-default" data-bind="click: toggleEditPassword">Change
25+
password</button>
2526
<button type="button" class="button button-default" data-bind="click: closeAccount">Close account</button>
2627
</div>
2728
</div>
@@ -36,8 +37,8 @@
3637
<div class="row">
3738
<div class="col-md-3"><label for="firstName">First name</label></div>
3839
<div class="col-md-9">
39-
<input type="text" class="form-control" aria-required="true" autofocus="autofocus" id="firstName" name="firstName"
40-
autocomplete="first-name" data-bind="textInput: firstName" />
40+
<input type="text" class="form-control" aria-required="true" autofocus="autofocus" id="firstName"
41+
name="firstName" autocomplete="first-name" data-bind="textInput: firstName" />
4142
</div>
4243
</div>
4344
<div class="row">
@@ -57,7 +58,8 @@
5758
<!-- /ko -->
5859
<!-- ko ifnot: working -->
5960
<div class="col-md-12">
60-
<button type="button" class="button button-default" data-bind="click: changeAccountInfo, enable: isUserChanged()">Save</button>
61+
<button type="button" class="button button-default"
62+
data-bind="click: changeAccountInfo, enable: isUserChanged()">Save</button>
6163
<button type="button" class="button button-default" data-bind="click: toggleEdit">Cancel</button>
6264
</div>
6365
<!-- /ko -->

src/services/IStaticDataProvider.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export default interface IStaticDataProvider {
2+
getStaticData(objectType: string): Promise<any>;
3+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import path = require("path");
2+
import IStaticDataProvider from "./IStaticDataProvider";
3+
const fs = require('fs');
4+
5+
export class PublisherStaticDataProvider implements IStaticDataProvider {
6+
getStaticData(objectType: string): Promise<any> {
7+
let fullPath = objectType == "defaultStaticData.json" ?
8+
path.join(__dirname, '../../tests/mocks/defaultStaticData.json') : path.join(__dirname, '../../templates/default.json');
9+
let filePath = path.resolve(fullPath);
10+
11+
return new Promise<any>((resolve, reject) => {
12+
fs.readFile(filePath, { encoding: 'utf-8' }, function (err, data) {
13+
if (err) {
14+
reject();
15+
return;
16+
}
17+
18+
const obj = JSON.parse(data);
19+
resolve(obj);
20+
});
21+
});
22+
}
23+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { HttpMethod } from "@paperbits/common/http";
2+
import { XmlHttpRequestClient } from "@paperbits/common/http/xmlHttpRequestClient";
3+
import IStaticDataProvider from "./IStaticDataProvider";
4+
5+
export class RuntimeStaticDataProvider implements IStaticDataProvider {
6+
private readonly httpClient: XmlHttpRequestClient;
7+
constructor() {
8+
this.httpClient = new XmlHttpRequestClient();
9+
}
10+
getStaticData(objectType: string): Promise<any> {
11+
let path = objectType == "defaultStaticData.json" ? "/tests/mocks/defaultStaticData.json" : "/editors/templates/default.json";
12+
13+
return new Promise<any>(async (resolve, reject) => {
14+
let result = await this.httpClient.send({
15+
method: HttpMethod.get,
16+
url: path,
17+
headers: [],
18+
body: {}
19+
});
20+
resolve(result.toObject());
21+
});
22+
}
23+
}

0 commit comments

Comments
 (0)