Skip to content

Commit

Permalink
[core] Bugfix/media capabilities use effect (#55)
Browse files Browse the repository at this point in the history
* doc: improved code styling in readme

* infra: uninstalled react-dom

* chore: cleaned up

* infra: extracted supported from hook in useMediaCapabilities

* doc: cleaned code snippet for useMediaCapabilities in README

* [fix] added use effect dependencies in useMediaCapabilitiesDecodingInfo

* fix: removed unnecessary code

* [fix] fixed media capabilities unit test in the basic level

* [fix] push supported into hook for easy unit test

* [fix] uninstalled @babel/plugin-transform-runtime
  • Loading branch information
anton-karlovskiy authored Mar 27, 2020
1 parent 40b093a commit 1b5b5cf
Show file tree
Hide file tree
Showing 5 changed files with 212 additions and 173 deletions.
42 changes: 21 additions & 21 deletions babel.config.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the 'License');
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an 'AS IS' BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

module.exports = {
presets: [
"@babel/preset-env"
]
};
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the 'License');
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an 'AS IS' BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

module.exports = {
presets: [
"@babel/preset-env"
]
};
74 changes: 35 additions & 39 deletions media-capabilities/index.js
Original file line number Diff line number Diff line change
@@ -1,39 +1,35 @@
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { useState, useEffect } from 'react';

const supported = typeof window !== 'undefined' && 'mediaCapabilities' in navigator;

const useMediaCapabilitiesDecodingInfo = (mediaDecodingConfig, initialMediaCapabilitiesInfo = {}) => {
initialMediaCapabilitiesInfo = {
...initialMediaCapabilitiesInfo
};

const [mediaCapabilitiesInfo, setMediaCapabilitiesInfo] = useState(initialMediaCapabilitiesInfo);

useEffect(() => {
supported &&
navigator
.mediaCapabilities
.decodingInfo(mediaDecodingConfig)
.then(setMediaCapabilitiesInfo)
.catch(error => console.error(error));
}, []);

return { supported, mediaCapabilitiesInfo };
};

export { useMediaCapabilitiesDecodingInfo };
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { useState, useEffect } from 'react';

const useMediaCapabilitiesDecodingInfo = (mediaDecodingConfig, initialMediaCapabilitiesInfo = {}) => {
const supported = typeof navigator !== 'undefined' && 'mediaCapabilities' in navigator;
const [mediaCapabilitiesInfo, setMediaCapabilitiesInfo] = useState(initialMediaCapabilitiesInfo);

useEffect(() => {
supported &&
navigator
.mediaCapabilities
.decodingInfo(mediaDecodingConfig)
.then(setMediaCapabilitiesInfo)
.catch(error => console.error(error));
}, [mediaDecodingConfig]);

return { supported, mediaCapabilitiesInfo };
};

export { useMediaCapabilitiesDecodingInfo };
229 changes: 117 additions & 112 deletions media-capabilities/media-capabilities.test.js
Original file line number Diff line number Diff line change
@@ -1,112 +1,117 @@
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the 'License');
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an 'AS IS' BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { renderHook } from '@testing-library/react-hooks';

const mediaDecodingConfig = {
type: 'file',
audio: {
contentType: 'audio/mp3',
channels: 2,
bitrate: 132700,
samplerate: 5200
}
};

const mediaCapabilitiesMapper = {
'audio/mp3': {
powerEfficient: true,
smooth: true,
supported: true
}
};

describe('useMediaCapabilitiesDecodingInfo', () => {
test('should return supported flag on unsupported platforms', () => {
jest.isolateModules(() => {
const { useMediaCapabilitiesDecodingInfo } = require('.');
const { result } = renderHook(() => useMediaCapabilitiesDecodingInfo(mediaDecodingConfig));

expect(result.current.supported).toEqual(false);
})
});

test('should return supported flag on unsupported platforms and no config given', () => {
jest.isolateModules(() => {
const { useMediaCapabilitiesDecodingInfo } = require('.');
const { result } = renderHook(() => useMediaCapabilitiesDecodingInfo());

expect(result.current.supported).toEqual(false);
})
});

test('should return initialMediaCapabilitiesInfo for unsupported', () => {
jest.isolateModules(() => {
const initialMediaCapabilitiesInfo = {
supported: true,
smooth: false,
powerEfficient: true
};

const { useMediaCapabilitiesDecodingInfo } = require('.');
const { result } = renderHook(() => useMediaCapabilitiesDecodingInfo(mediaDecodingConfig, initialMediaCapabilitiesInfo));

expect(result.current.mediaCapabilitiesInfo.supported).toBe(true);
expect(result.current.mediaCapabilitiesInfo.smooth).toEqual(false);
expect(result.current.mediaCapabilitiesInfo.powerEfficient).toEqual(true);
});
});

test('should return supported flag when no config given', (done) => {
jest.isolateModules(() => {
global.navigator.mediaCapabilities = {
decodingInfo: () => new Promise(resolve => resolve(true))
};

const { useMediaCapabilitiesDecodingInfo } = require('.');
const { result, waitForNextUpdate } = renderHook(() => useMediaCapabilitiesDecodingInfo());

waitForNextUpdate()
.then(() => {
expect(result.current.supported).toEqual(true);

done();
})
.catch(err => done(err));
});
});

test('should return mediaCapabilitiesInfo for given media configuration', (done) => {
jest.isolateModules(() => {
global.navigator.mediaCapabilities = {
decodingInfo: () => new Promise(resolve => resolve(mediaCapabilitiesMapper[mediaDecodingConfig.audio.contentType]))
};

const { useMediaCapabilitiesDecodingInfo } = require('.');
const { result, waitForNextUpdate } = renderHook(() => useMediaCapabilitiesDecodingInfo(mediaDecodingConfig));

waitForNextUpdate()
.then(() => {
expect(result.current.mediaCapabilitiesInfo.powerEfficient).toEqual(true);
expect(result.current.mediaCapabilitiesInfo.smooth).toEqual(true);
expect(result.current.mediaCapabilitiesInfo.supported).toEqual(true);

done();
})
.catch(err => done(err));
});
});
});
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the 'License');
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an 'AS IS' BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import 'babel-polyfill';
import { renderHook } from '@testing-library/react-hooks';

const mediaDecodingConfig = {
type: 'file',
audio: {
contentType: 'audio/mp3',
channels: 2,
bitrate: 132700,
samplerate: 5200
}
};

const mediaCapabilitiesMapper = {
'audio/mp3': {
powerEfficient: true,
smooth: true,
supported: true
}
};

describe('useMediaCapabilitiesDecodingInfo', () => {
test('should return supported flag on unsupported platforms', () => {
const { useMediaCapabilitiesDecodingInfo } = require('./');
const { result } = renderHook(() => useMediaCapabilitiesDecodingInfo(mediaDecodingConfig));

expect(result.current.supported).toEqual(false);
});

test('should return supported flag on unsupported platforms and no config given', () => {
const { useMediaCapabilitiesDecodingInfo } = require('./');
const { result } = renderHook(() => useMediaCapabilitiesDecodingInfo());

expect(result.current.supported).toEqual(false);
});

test('should return initialMediaCapabilitiesInfo for unsupported', () => {
const initialMediaCapabilitiesInfo = {
supported: true,
smooth: false,
powerEfficient: true
};

const { useMediaCapabilitiesDecodingInfo } = require('./');
const { result } = renderHook(() => useMediaCapabilitiesDecodingInfo(mediaDecodingConfig, initialMediaCapabilitiesInfo));

expect(result.current.mediaCapabilitiesInfo.supported).toBe(true);
expect(result.current.mediaCapabilitiesInfo.smooth).toEqual(false);
expect(result.current.mediaCapabilitiesInfo.powerEfficient).toEqual(true);
});

test('should return supported flag when no config given', async () => {
const originalError = console.error;
console.error = jest.fn();

const mockDecodingInfo = jest.fn().mockImplementation(() => Promise.resolve({
supported: true
}));

global.navigator.mediaCapabilities = {
decodingInfo: mockDecodingInfo
};

const { useMediaCapabilitiesDecodingInfo } = require('./');

try {
const { result, waitForNextUpdate } = renderHook(() => useMediaCapabilitiesDecodingInfo());
await waitForNextUpdate();

expect(result.current.supported).toEqual(true);
} finally {
console.error = originalError;
}
});

test('should return mediaCapabilitiesInfo for given media configuration', async () => {
const originalError = console.error;
console.error = jest.fn();

const mockDecodingInfo = jest.fn().mockImplementation(() => Promise.resolve({
...mediaCapabilitiesMapper[mediaDecodingConfig.audio.contentType]
}));

global.navigator.mediaCapabilities = {
decodingInfo: mockDecodingInfo
};

const { useMediaCapabilitiesDecodingInfo } = require('./');

try {
const { result, waitForNextUpdate } = renderHook(() => useMediaCapabilitiesDecodingInfo(mediaDecodingConfig));
await waitForNextUpdate();

expect(result.current.mediaCapabilitiesInfo.powerEfficient).toEqual(true);
expect(result.current.mediaCapabilitiesInfo.smooth).toEqual(true);
expect(result.current.mediaCapabilitiesInfo.supported).toEqual(true);
} finally {
console.error = originalError;
}
});
});
Loading

0 comments on commit 1b5b5cf

Please sign in to comment.