Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

💚 Add Windows workflow #176

Merged
merged 9 commits into from
Feb 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions .github/workflows/windows.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
name: Windows
on: push
jobs:
build:
name: Build
runs-on: windows-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: 12
- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- uses: actions/cache@v2
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: v1/${{ runner.os }}/node-12/${{ hashFiles('**/yarn.lock') }}
restore-keys: v1/${{ runner.os }}/node-12/
- run: yarn
- run: yarn build
- uses: actions/upload-artifact@v2
with:
name: dist
path: packages/*/dist

test:
name: Test ${{ matrix.package }}
needs: [build]
strategy:
matrix:
package:
- '@percy/env'
- '@percy/client'
- '@percy/dom'
- '@percy/logger'
- '@percy/config'
- '@percy/core'
- '@percy/cli'
- '@percy/cli-command'
- '@percy/cli-exec'
- '@percy/cli-snapshot'
- '@percy/cli-upload'
- '@percy/cli-build'
- '@percy/cli-config'
- '@percy/sdk-utils'
runs-on: windows-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: 12
- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- uses: actions/cache@v2
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: v1/${{ runner.os }}/node-12/${{ hashFiles('**/yarn.lock') }}
restore-keys: v1/${{ runner.os }}/node-12/
- uses: actions/download-artifact@v2
with:
name: dist
path: packages
- run: yarn
- name: Run tests
run: yarn workspace ${{ matrix.package }} test --colors
11 changes: 7 additions & 4 deletions packages/cli-config/test/create.test.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import path from 'path';
import expect from 'expect';
import { logger, getMockConfig } from './helpers';
import { Create } from '../src/commands/config/create';
Expand Down Expand Up @@ -47,14 +48,16 @@ describe('percy config:create', () => {
});

it('can create specific config files', async () => {
await Create.run(['config/percy.config.js']);
let filename = path.join('.config', 'percy.config.js');
await Create.run([filename]);
expect(logger.stderr).toEqual([]);
expect(logger.stdout).toEqual(['[percy] Created Percy config: config/percy.config.js\n']);
expect(getMockConfig('config/percy.config.js')).toBe(PercyConfig.stringify('js'));
expect(logger.stdout).toEqual([`[percy] Created Percy config: ${filename}\n`]);
expect(getMockConfig(filename)).toBe(PercyConfig.stringify('js'));
});

it('logs an error and exits when the filetype is unsupported', async () => {
await expect(Create.run(['config/percy.config.php'])).rejects.toThrow('EEXIT: 1');
await expect(Create.run([path.join('.config', 'percy.config.php')]))
.rejects.toThrow('EEXIT: 1');
expect(logger.stdout).toEqual([]);
expect(logger.stderr).toEqual(['[percy] Unsupported filetype: php\n']);
});
Expand Down
9 changes: 6 additions & 3 deletions packages/cli-config/test/migrate.test.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import path from 'path';
import expect from 'expect';
import PercyConfig from '@percy/config';
import { logger, mockConfig, getMockConfig } from './helpers';
Expand Down Expand Up @@ -76,7 +77,7 @@ describe('percy config:migrate', () => {
});

it('errors and exits when a config cannot be found', async () => {
await expect(Migrate.run(['.config/percy.yml']))
await expect(Migrate.run([path.join('.config', 'percy.yml')]))
.rejects.toThrow('EEXIT: 1');

expect(logger.stdout).toEqual([]);
Expand All @@ -86,11 +87,13 @@ describe('percy config:migrate', () => {
});

it('errors and exits when a config cannot be parsed', async () => {
mockConfig('.config/percy.yml', () => {
let filename = path.join('.config', 'percy.yml');

mockConfig(filename, () => {
throw new Error('test');
});

await expect(Migrate.run(['.config/percy.yml']))
await expect(Migrate.run([filename]))
.rejects.toThrow('EEXIT: 1');

expect(logger.stdout).toEqual([]);
Expand Down
8 changes: 5 additions & 3 deletions packages/cli-config/test/validate.test.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import path from 'path';
import expect from 'expect';
import { logger, mockConfig } from './helpers';
import { Validate } from '../src/commands/config/validate';
Expand Down Expand Up @@ -43,12 +44,13 @@ describe('percy config:validate', () => {
});

it('logs debug info for a provided valid config file', async () => {
mockConfig('config/percy.yml', 'version: 2\ntest:\n value: config');
await Validate.run(['config/percy.yml']);
let filename = path.join('.config', 'percy.yml');
mockConfig(filename, 'version: 2\ntest:\n value: config');
await Validate.run([filename]);

expect(logger.stderr).toEqual([]);
expect(logger.stdout).toEqual([
'[percy] Found config file: config/percy.yml\n',
`[percy] Found config file: ${filename}\n`,
'[percy] Using config:\n' + [
'{',
' version: 2,',
Expand Down
18 changes: 9 additions & 9 deletions packages/cli-exec/test/exec.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@ describe('percy exec', () => {
});

it('starts and stops the percy process around the command', async () => {
await Exec.run(['--', 'sleep', '0.1']);
await Exec.run(['--', 'node', '--eval', '']);

expect(logger.stderr).toEqual([]);
expect(logger.stdout).toEqual([
'[percy] Percy has started!\n',
'[percy] Created build #1: https://percy.io/test/test/123\n',
'[percy] Running "sleep 0.1"\n',
'[percy] Running "node --eval "\n',
'[percy] Stopping percy...\n',
'[percy] Finalized build #1: https://percy.io/test/test/123\n',
'[percy] Done!\n'
Expand All @@ -47,13 +47,13 @@ describe('percy exec', () => {

it('sets the parallel total when the --parallel flag is provided', async () => {
expect(process.env.PERCY_PARALLEL_TOTAL).toBeUndefined();
await Exec.run(['--parallel', '--', 'sleep', '0.1']);
await Exec.run(['--parallel', '--', 'node', '--eval', '']);

expect(logger.stderr).toEqual([]);
expect(logger.stdout).toEqual([
'[percy] Percy has started!\n',
'[percy] Created build #1: https://percy.io/test/test/123\n',
'[percy] Running "sleep 0.1"\n',
'[percy] Running "node --eval "\n',
'[percy] Stopping percy...\n',
'[percy] Finalized build #1: https://percy.io/test/test/123\n',
'[percy] Done!\n'
Expand All @@ -64,32 +64,32 @@ describe('percy exec', () => {

it('runs the command even when percy is disabled', async () => {
process.env.PERCY_ENABLE = '0';
await Exec.run(['--', 'sleep', '0.1']);
await Exec.run(['--', 'node', '--eval', '']);

expect(logger.stderr).toEqual([]);
expect(logger.stdout).toEqual([]);
});

it('runs the command even when PERCY_TOKEN is missing', async () => {
delete process.env.PERCY_TOKEN;
await Exec.run(['--', 'sleep', '0.1']);
await Exec.run(['--', 'node', '--eval', '']);

expect(logger.stderr).toEqual([]);
expect(logger.stdout).toEqual([
'[percy] Skipping visual tests - Missing Percy token\n',
'[percy] Running "sleep 0.1"\n'
'[percy] Running "node --eval "\n'
]);
});

it('forwards the command status', async () => {
await expect(Exec.run(['--', 'bash', '-c', 'exit 3']))
await expect(Exec.run(['--', 'node', '--eval', 'process.exit(3)']))
.rejects.toThrow('EEXIT: 3');

expect(logger.stderr).toEqual([]);
expect(logger.stdout).toEqual([
'[percy] Percy has started!\n',
'[percy] Created build #1: https://percy.io/test/test/123\n',
'[percy] Running "bash -c exit 3"\n',
'[percy] Running "node --eval process.exit(3)"\n',
'[percy] Stopping percy...\n',
'[percy] Finalized build #1: https://percy.io/test/test/123\n',
'[percy] Done!\n'
Expand Down
8 changes: 5 additions & 3 deletions packages/config/test/index.test.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import path from 'path';
import expect from 'expect';
import logger from '@percy/logger/test/helper';
import mockConfig from './helper';
Expand Down Expand Up @@ -225,23 +226,24 @@ describe('PercyConfig', () => {
});

it('can search a provided directory for a config file', () => {
let filename = path.join('config', '.percy.yml');
logger.loglevel('debug');

mockConfig('config/.percy.yml', [
mockConfig(filename, [
'version: 2',
'test:',
' value: config/percy'
].join('\n'));

expect(PercyConfig.load({ path: 'config/' }))
expect(PercyConfig.load({ path: 'config' }))
.toEqual({
version: 2,
test: { value: 'config/percy' }
});

expect(logger.stdout).toEqual([]);
expect(logger.stderr).toContain(
'[percy:config] Found config file: config/.percy.yml\n'
`[percy:config] Found config file: ${filename}\n`
);
});

Expand Down
5 changes: 5 additions & 0 deletions packages/core/src/discovery/browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,11 @@ export default class Browser extends EventEmitter {

// after closing, attempt to clean up the profile directory
await closed.then(() => new Promise(resolve => {
// needed due to a bug in Node 12 - https://github.com/nodejs/node/issues/27097
this.process?.stdin.end();
this.process?.stdout.end();
this.process?.stderr.end();

/* istanbul ignore else: sanity */
if (this.profile) {
rimraf(this.profile, error => {
Expand Down
5 changes: 2 additions & 3 deletions packages/core/src/utils/install-browser.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/* istanbul ignore file: this utility is required to work before tests to download the browser
* binary; since it is technically tested before the tests run, it does not generate coverage */
import path from 'path';
import https from 'https';
import {
Expand All @@ -10,7 +12,6 @@ import logger from '@percy/logger';
import readableBytes from './bytes';

// used to determine platform defaults
/* istanbul ignore next: hard to cover sans combined reports */
const platform = (
process.platform === 'win32' && process.arch === 'x64'
? 'win64' : process.platform
Expand Down Expand Up @@ -63,7 +64,6 @@ export default async function install({
// download the file at the given URL and log progress
await new Promise((resolve, reject) => {
https.get(url, response => {
/* istanbul ignore next: failsafe */
if (response.statusCode !== 200) {
response.resume();
reject(new Error(`Download failed: ${response.statusCode} - ${url}`));
Expand Down Expand Up @@ -96,7 +96,6 @@ export default async function install({
logger().info(`Successfully downloaded ${browser}`);
} finally {
// always cleanup
/* istanbul ignore next: hard to cover download failure */
if (existsSync(dlpath)) {
await new Promise(resolve => rimraf(dlpath, resolve));
}
Expand Down
2 changes: 1 addition & 1 deletion packages/core/test/helpers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ afterEach(function(done) {
}

// cleanup tmp files
rimraf(path.join(os.tmpdir(), 'percy'), done);
rimraf(path.join(os.tmpdir(), 'percy'), () => done());
});

export { logger, mockAPI };
Expand Down
21 changes: 0 additions & 21 deletions packages/core/test/percy.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -172,27 +172,6 @@ describe('Percy', () => {
await expect(Percy.start({ token: 'PERCY_TOKEN' })).rejects
.toThrow('Percy is already running or the port is in use');
});

it('maybe downloads the browser for asset discovery', async function() {
let local = require('path').join(__dirname, '../.local-chromium');
let { existsSync } = require('fs');

this.retries(5); // this flakes on windows due to its non-atomic fs functions
require('rimraf').sync(local);
expect(existsSync(local)).toBe(false);
this.retries(0);

// the install script will always log
percy.loglevel('silent');

this.timeout(0); // this might take a minute to download
await percy.start();
expect(existsSync(local)).toBe(true);

expect(logger.stderr).toEqual([]);
expect(logger.stdout[0]).toEqual('[percy] Chromium not found, downloading...\n');
expect(logger.stdout[logger.stdout.length - 1]).toEqual('[percy] Successfully downloaded Chromium\n');
});
});

describe('#stop()', () => {
Expand Down
11 changes: 4 additions & 7 deletions packages/dom/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,16 @@
"babel": {
"extends": "../../babel.config.js",
"presets": [
[
"@babel/env",
{
"targets": "last 2 version"
}
]
["@babel/env", {
"targets": "last 2 version"
}]
]
},
"devDependencies": {
"@rollup/plugin-babel": "^5.2.2",
"@rollup/plugin-commonjs": "^17.0.0",
"@rollup/plugin-node-resolve": "^11.1.0",
"interactor.js": "^2.0.0-beta.8",
"interactor.js": "^2.0.0-beta.10",
"karma": "^6.0.2",
"karma-chrome-launcher": "^3.1.0",
"karma-coverage": "^2.0.3",
Expand Down
6 changes: 3 additions & 3 deletions scripts/babel-register.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ require('@babel/register')({
rootMode: 'upward',
babelrcRoots: ['.'],

// specified without the cwd so tests can share helpers
only: [
// specified without the cwd so tests can share helpers
new RegExp(
['packages', '.*?', '(src|test)']
// escape windows path seperators and escape the escape
['(@percy|packages)', '.+?', '(src|test)']
// escape windows path separators and escape the escape
.join(path.sep === '/' ? '/' : '\\\\')
)
]
Expand Down
2 changes: 1 addition & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5161,7 +5161,7 @@ inquirer@^6.2.0:
strip-ansi "^5.1.0"
through "^2.3.6"

interactor.js@^2.0.0-beta.8:
interactor.js@^2.0.0-beta.10:
version "2.0.0-beta.10"
resolved "https://registry.yarnpkg.com/interactor.js/-/interactor.js-2.0.0-beta.10.tgz#f009c769d535bfe78794caf3d85b6c46675b9b18"
integrity sha512-PI6bW6spipafmdT0BdodS90wDIeFSK4OL/0WK79Vb3z7a0GYsQyZSgIIH11zWqofe0CNpxIrdj6pbG/EpQ8+Tw==
Expand Down