88 lines
6.2 KiB
JavaScript
88 lines
6.2 KiB
JavaScript
'use strict';
|
|
var fs = require('fs');
|
|
var path = require('path');
|
|
var root = path.resolve(__dirname, '..');
|
|
var passed = 0;
|
|
function read(file) { return fs.readFileSync(path.join(root, file), 'utf8'); }
|
|
function json(file) { return JSON.parse(read(file)); }
|
|
function assert(condition, message) { if (!condition) { throw new Error(message); } passed++; }
|
|
|
|
var packageJson = json('package.json');
|
|
var packageSolution = json('config/package-solution.json');
|
|
var config = json('config/config.json');
|
|
var manifest = json('src/webparts/organizationChart/OrganizationChartWebPart.manifest.json');
|
|
var service = read('src/webparts/organizationChart/OrganizationChartDataService.ts');
|
|
var listService = read('src/webparts/organizationChart/OrganizationChartListDataService.ts');
|
|
var webPart = read('src/webparts/organizationChart/OrganizationChartWebPart.ts');
|
|
var component = read('src/webparts/organizationChart/components/OrganizationChart.tsx');
|
|
var picker = read('src/webparts/organizationChart/components/OrganizationChartPeoplePicker.tsx');
|
|
var styles = read('src/webparts/organizationChart/components/OrganizationChart.module.scss');
|
|
|
|
assert(packageJson.name === 'organization-chart-webpart', 'Package name is inconsistent.');
|
|
assert(packageSolution.solution.name === packageJson.name && packageSolution.solution.title === packageJson.name,
|
|
'Solution name is inconsistent.');
|
|
assert(packageSolution.paths.zippedPackage === 'solution/organization-chart-webpart.sppkg', 'Package file name is inconsistent.');
|
|
assert(packageSolution.solution.includeClientSideAssets === true && packageSolution.solution.skipFeatureDeployment === true,
|
|
'Central deployment is not configured.');
|
|
assert(!!config.bundles['organization-chart-webpart'], 'Bundle name is inconsistent.');
|
|
assert(manifest.componentType === 'WebPart' && manifest.alias === 'OrganizationChartWebPart', 'Manifest is invalid.');
|
|
assert(packageJson.version === '1.2.1' && packageSolution.solution.version === '1.2.1.0',
|
|
'Organization Chart version is inconsistent.');
|
|
assert(webPart.indexOf("PropertyPaneTextField('title'") >= 0 && component.indexOf('styles.heading') >= 0,
|
|
'Configurable web part title is missing.');
|
|
assert(webPart.indexOf("String(this.properties.title || '').trim()") >= 0,
|
|
'An empty web part title must remain hidden.');
|
|
assert(service.indexOf('/_api/SP.UserProfiles.PeopleManager/GetPropertiesFor') >= 0, 'User Profile REST access is missing.');
|
|
assert(service.indexOf('/_api/SP.UserProfiles.PeopleManager/GetMyProperties') >= 0,
|
|
'Reliable current-user profile access is missing.');
|
|
assert(service.indexOf('ClientPeoplePickerWebServiceInterface.clientPeoplePickerSearchUser') >= 0,
|
|
'Configured-account resolution through the SharePoint People Picker is missing.');
|
|
assert(service.indexOf('profile.directReports') >= 0 && service.indexOf('this.buildNode(childAccount, depth + 1') >= 0,
|
|
'Recursive downward organization loading is missing.');
|
|
assert(webPart.indexOf("PropertyPaneDropdown('dataSource'") >= 0 &&
|
|
webPart.indexOf("PropertyPaneDropdown('listId'") >= 0 &&
|
|
webPart.indexOf("PropertyPaneDropdown('listManagerField'") >= 0,
|
|
'SharePoint list data-source configuration is missing.');
|
|
assert(listService.indexOf('/_api/web/lists') >= 0 && listService.indexOf('getOrganization') >= 0 &&
|
|
listService.indexOf('manager.directReports.push') >= 0,
|
|
'SharePoint list organization tree loading is missing.');
|
|
assert(webPart.indexOf('OrganizationChartPeoplePicker') >= 0 &&
|
|
webPart.indexOf("PropertyPaneTextField('startUser'") < 0,
|
|
'The verified starting-person picker must be rendered on the canvas instead of the property pane.');
|
|
assert(webPart.indexOf('DisplayMode.Edit && !this.isListSource()') >= 0,
|
|
'The User Profile people picker must be hidden for SharePoint-list data sources.');
|
|
assert(picker.indexOf('NormalPeoplePicker') >= 0 && picker.indexOf('ValidationState.invalid') >= 0,
|
|
'The on-canvas people picker must reject unverified free-text values.');
|
|
assert(webPart.indexOf("PropertyPaneSlider('maxDepth'") >= 0 && webPart.indexOf("PropertyPaneSlider('maxPeople'") >= 0,
|
|
'Tree safety limits are missing.');
|
|
assert(component.indexOf("role='tree'") >= 0 && component.indexOf("role='treeitem'") >= 0,
|
|
'Accessible tree semantics are missing.');
|
|
assert(component.indexOf('aria-expanded') >= 0 && component.indexOf('aria-selected={false}') >= 0,
|
|
'Accessible tree state is missing.');
|
|
assert(component.indexOf('peopleCountLabel') < 0 && component.indexOf('') >= 0 &&
|
|
component.indexOf('') >= 0, 'Header count removal or detail chevrons are missing.');
|
|
assert(component.indexOf('styles.toggle') < 0 && styles.indexOf('.toggle {') < 0 &&
|
|
component.indexOf('collapsed') < 0, 'Branch toggle circles must not be rendered.');
|
|
assert(styles.indexOf('box-shadow') < 0 && styles.indexOf('border-radius: 0 4px') < 0,
|
|
'Cards must be shadowless and connectors must use straight corners.');
|
|
assert(styles.indexOf('.tree li:only-child { padding-top: 0; }') >= 0,
|
|
'Single-child connector spacing must remain continuous.');
|
|
assert(component.indexOf('getMaximumVisibleBreadth') >= 0 && component.indexOf('getBreadthCardWidth') >= 0 &&
|
|
component.indexOf('maximumBreadth === 4') >= 0 && component.indexOf('cardWidth') >= 0 &&
|
|
styles.indexOf('.compactTree') >= 0 && styles.indexOf('.denseTree') >= 0,
|
|
'Responsive organization-chart card sizing is missing.');
|
|
assert(component.indexOf('expandedDetails') >= 0 && component.indexOf('toggleDetails') >= 0 &&
|
|
component.indexOf('renderDetails') >= 0 && component.indexOf("className={styles.cardContent}") >= 0,
|
|
'Teams-style expandable person cards are missing.');
|
|
assert(webPart.indexOf("PropertyPaneTextField('cardBackgroundColor'") >= 0 &&
|
|
webPart.indexOf("PropertyPaneTextField('cardAccentColor'") >= 0 &&
|
|
webPart.indexOf("PropertyPaneToggle('roundedCards'") >= 0,
|
|
'Configurable card design options are missing.');
|
|
assert(component.indexOf("role='presentation'") >= 0, 'Decorative profile images must be hidden from assistive technology.');
|
|
['bodyText', 'neutralSecondary', 'neutralLighter', 'themePrimary', 'neutralTertiary', 'white', 'neutralLight', 'focusBorder', 'errorText']
|
|
.forEach(function(slot) {
|
|
assert(styles.indexOf('[theme:' + slot + ', default:') >= 0, 'SharePoint theme slot is missing: ' + slot);
|
|
});
|
|
|
|
console.log('Organization Chart project validation passed: ' + passed);
|