Skip to content

Commit b1d14fc

Browse files
committed
Initial commit.
0 parents  commit b1d14fc

26 files changed

+10594
-0
lines changed

.babelrc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"presets": [
3+
"@babel/env",
4+
"@babel/typescript"
5+
],
6+
"plugins": [
7+
"@babel/proposal-class-properties",
8+
"@babel/proposal-object-rest-spread"
9+
]
10+
}

.editorconfig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
root = true
2+
3+
[*]
4+
indent_style = tab
5+
end_of_line = lf
6+
charset = utf-8
7+
trim_trailing_whitespace = true
8+
insert_final_newline = true
9+
10+
[*.yml]
11+
indent_style = space
12+
indent_size = 2

.gitattributes

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
* text=auto eol=lf
2+
*.qsys binary

.github/workflows/node.js.yml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
2+
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
3+
4+
name: Node.js Build
5+
6+
on: [push, pull_request]
7+
8+
jobs:
9+
build:
10+
11+
runs-on: ubuntu-latest
12+
13+
strategy:
14+
matrix:
15+
node-version: [10.x, 12.x, 14.x]
16+
17+
steps:
18+
- uses: actions/checkout@v2
19+
- name: Use Node.js ${{ matrix.node-version }}
20+
uses: actions/setup-node@v1
21+
with:
22+
node-version: ${{ matrix.node-version }}
23+
- run: npm ci
24+
- run: npm run build --if-present
25+
- run: npm test

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
node_modules
2+
yarn.lock
3+
dist
4+
integration-tests/design-location.json

@types/pump.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
declare module 'pump';

_register.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/* eslint-disable @typescript-eslint/no-var-requires */
2+
// Set up the environment for tests and development.
3+
// TODO: This should be allowed in XO by default
4+
require('any-observable/register/zen');
5+
6+
require('@babel/polyfill');
7+
8+
require('@babel/register')({
9+
extensions: ['.js', '.ts']
10+
});

images/type-hinting.png

102 KB
Loading
17 KB
Binary file not shown.
Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
import fs from 'fs';
2+
import path from 'path';
3+
import {ExecutionContext, serial as rawTest} from 'ava'; // eslint-disable-line ava/use-test
4+
import delay from 'delay';
5+
import isCI from 'is-ci';
6+
import pEvent from 'p-event';
7+
import QrcClient from '../src/qrc-client';
8+
import {
9+
getStatus,
10+
logon,
11+
getNamedControls,
12+
setNamedControl,
13+
getComponentControls,
14+
setComponentControls,
15+
addNamedControlToGroup,
16+
addComponentControlsToGroup,
17+
pollGroup,
18+
invalidateGroup,
19+
clearGroup,
20+
destroyGroup,
21+
removeNamedControlsFromGroup
22+
} from '../src/commands';
23+
24+
const test = isCI ? rawTest.skip : rawTest;
25+
26+
let connectionJSON;
27+
28+
try {
29+
connectionJSON = fs.readFileSync(path.join(__dirname, 'design-location.json'), 'utf8');
30+
} catch {
31+
connectionJSON = '{"host": "127.0.0.1", "port": 1710}';
32+
}
33+
34+
const connectionInfo: {host: string; port: number} = JSON.parse(connectionJSON);
35+
36+
const withEmulator = async (t: ExecutionContext, run: (t: ExecutionContext, client: QrcClient) => any): Promise<any> => {
37+
const client = new QrcClient();
38+
client.on('error', error => t.fail(`Error was thrown: ${String(error)}`));
39+
40+
const connectEvent = pEvent(client, 'connect');
41+
const closeEvent = pEvent(client, 'close');
42+
43+
client.connect(connectionInfo);
44+
await connectEvent;
45+
await client.send(setNamedControl('AllOff', true));
46+
await run(t, client);
47+
client.end();
48+
await closeEvent;
49+
};
50+
51+
test('getStatus', withEmulator, async (t: ExecutionContext, client: QrcClient) => {
52+
const status = await client.send(getStatus());
53+
54+
t.is(status.DesignName, 'Basic-Commands-Test');
55+
t.is(status.IsRedundant, false);
56+
t.is(status.IsEmulator, true);
57+
t.is(status.State, 'Active');
58+
t.is(status.Platform, 'Emulator');
59+
t.true(typeof status.DesignCode === 'string');
60+
61+
t.is(status.Status.Code, 0);
62+
t.is(status.Status.String, 'OK');
63+
});
64+
65+
test('logon', withEmulator, async (t: ExecutionContext, client: QrcClient) => {
66+
t.true(await client.send(logon('james', 'password')));
67+
});
68+
69+
test('getNamedControls', withEmulator, async (t: ExecutionContext, client: QrcClient) => {
70+
const [gain, mute] = await client.send(getNamedControls('GainGain', 'GainMute'));
71+
72+
t.is(gain.String, '-100dB');
73+
t.is(gain.Value, -100);
74+
t.is(gain.Position, 0);
75+
t.is(gain.Name, 'GainGain');
76+
77+
t.is(mute.String, 'unmuted');
78+
t.is(mute.Value, 0);
79+
t.is(mute.Position, 0);
80+
t.is(mute.Name, 'GainMute');
81+
});
82+
83+
test('setNamedControl', withEmulator, async (t: ExecutionContext, client: QrcClient) => {
84+
let gain = await client.send(setNamedControl('GainGain', {Value: 20}));
85+
86+
t.is(gain.String, '20.0dB');
87+
t.is(gain.Value, 20);
88+
t.is(gain.Position, 1);
89+
t.is(gain.Name, 'GainGain');
90+
91+
gain = await client.send(setNamedControl('GainGain', {Position: 0.5}));
92+
93+
t.is(gain.Value, -40);
94+
t.is(gain.Position, 0.5);
95+
96+
// Shorthand for Value
97+
gain = await client.send(setNamedControl('GainGain', 0));
98+
t.is(gain.Value, 0);
99+
});
100+
101+
test('getComponentControls', withEmulator, async (t: ExecutionContext, client: QrcClient) => {
102+
const component = await client.send(getComponentControls('MyGain', ['mute', 'gain']));
103+
104+
t.is(component.Name, 'MyGain');
105+
106+
const [mute, gain] = component.Controls;
107+
108+
t.is(gain.String, '-100dB');
109+
t.is(gain.Value, -100);
110+
t.is(gain.Position, 0);
111+
t.is(gain.Name, 'gain');
112+
113+
t.is(mute.String, 'unmuted');
114+
t.is(mute.Value, 0);
115+
t.is(mute.Position, 0);
116+
t.is(mute.Name, 'mute');
117+
});
118+
119+
test('setComponentControls', withEmulator, async (t: ExecutionContext, client: QrcClient) => {
120+
t.true(await client.send(setComponentControls('MyGain', [
121+
{Name: 'mute', Value: 1},
122+
{Name: 'gain', Position: 1}
123+
])));
124+
125+
const {Controls: [gain]} = await client.send(getComponentControls('MyGain', ['gain']));
126+
127+
t.is(gain.Value, 20);
128+
});
129+
130+
test('addNamedControlToGroup', withEmulator, async (t: ExecutionContext, client: QrcClient) => {
131+
t.true(await client.send(addNamedControlToGroup('my group', ['GainGain', 'GainMute'])));
132+
});
133+
134+
test('addComponentControlsToGroup', withEmulator, async (t: ExecutionContext, client: QrcClient) => {
135+
t.true(await client.send(addComponentControlsToGroup('my group', 'MyGain', ['bypass', 'invert'])));
136+
});
137+
138+
test('pollGroup', withEmulator, async (t: ExecutionContext, client: QrcClient) => {
139+
t.true(await client.send(addNamedControlToGroup('my group', ['GainGain', 'GainMute'])));
140+
141+
// TODO: We are currently relying on ordering for this test that is not guaranteed by the API.
142+
const {Id, Changes: [gain, mute]} = await client.send(pollGroup('my group'));
143+
144+
t.is(Id, 'my group');
145+
t.is(gain.Name, 'GainGain');
146+
t.is(gain.Value, -100);
147+
t.is(mute.Name, 'GainMute');
148+
t.is(mute.Value, 0);
149+
150+
const {Changes: {length}} = await client.send(pollGroup('my group'));
151+
152+
t.is(length, 0);
153+
});
154+
155+
test('invalidateGroup', withEmulator, async (t: ExecutionContext, client: QrcClient) => {
156+
t.true(await client.send(addNamedControlToGroup('my group', ['GainGain'])));
157+
158+
// TODO: fix types and expand this test
159+
await client.send(pollGroup('my group'));
160+
161+
const {Changes: {length}} = await client.send(pollGroup('my group'));
162+
t.is(length, 0);
163+
164+
t.true(await client.send(invalidateGroup('my group')));
165+
166+
const {Id, Changes: [gain]} = await client.send(pollGroup('my group'));
167+
168+
t.is(Id, 'my group');
169+
t.is(gain.Name, 'GainGain');
170+
t.is(gain.Value, -100);
171+
});
172+
173+
test('clearGroup', withEmulator, async (t: ExecutionContext, client: QrcClient) => {
174+
t.true(await client.send(addNamedControlToGroup('my group', ['GainGain', 'GainBypass'])));
175+
t.true(await client.send(clearGroup('my group')));
176+
t.true(await client.send(invalidateGroup('my group')));
177+
178+
const {Changes: {length}} = await client.send(pollGroup('my group'));
179+
t.is(length, 0);
180+
});
181+
182+
test('destroyGroup', withEmulator, async (t: ExecutionContext, client: QrcClient) => {
183+
t.true(await client.send(addNamedControlToGroup('my group', ['GainGain', 'GainBypass'])));
184+
t.true(await client.send(destroyGroup('my group')));
185+
await t.throwsAsync(async () => client.send(pollGroup('my group')), {message: /group.*does not exist/}, 'foo');
186+
});
187+
188+
test('removeNamedControlsFromGroup', withEmulator, async (t: ExecutionContext, client: QrcClient) => {
189+
t.true(await client.send(addNamedControlToGroup('my group', ['GainGain', 'GainBypass'])));
190+
t.true(await client.send(removeNamedControlsFromGroup('my group', ['GainBypass'])));
191+
t.true(await client.send(invalidateGroup('my group')));
192+
193+
const {Changes} = await client.send(pollGroup('my group'));
194+
t.is(Changes.length, 1);
195+
t.is(Changes[0].Name, 'GainGain');
196+
});
197+
198+
test('pollGroups', withEmulator, async (t: ExecutionContext, client: QrcClient) => {
199+
t.true(await client.send(addNamedControlToGroup('my group', ['GainGain', 'GainBypass'])));
200+
201+
const observable = client.pollGroup('my group');
202+
203+
const changes: any = [];
204+
observable.subscribe(value => changes.push(value.Changes));
205+
206+
await delay(500);
207+
208+
await client.send(setNamedControl('GainGain', {Position: 1}));
209+
210+
await delay(500);
211+
212+
t.deepEqual(changes, [
213+
[
214+
{Name: 'GainGain', String: '-100dB', Value: -100, Position: 0},
215+
{Name: 'GainBypass', String: 'no', Value: 0, Position: 0}
216+
],
217+
[
218+
{Name: 'GainGain', String: '20.0dB', Value: 20, Position: 1}
219+
]
220+
]);
221+
});

0 commit comments

Comments
 (0)