Skip to content

Commit

Permalink
Merge pull request #197 from adamgruber/video-embed
Browse files Browse the repository at this point in the history
feat: support video context as base64 data uri
  • Loading branch information
adamgruber authored Mar 25, 2022
2 parents 78daf62 + cba5a2c commit bbf3ad6
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 21 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# mochawesome-report-generator changelog

## [Unreleased]
### Added
- Support adding video in context via data uri [mochawesome #372](https://github.com/adamgruber/mochawesome/issues/372)

## [6.1.1] - 2022-03-05
### Fixed
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"lint": "eslint src test --ext js",
"stylelint": "stylelint src/**/*.css src/components/**/*.css",
"pretest": "npm run lint",
"test": "cross-env NODE_ENV=test nyc mocha \"test/spec/**/*.test.js\"",
"test": "cross-env NODE_ENV=test nyc mocha \"test/spec/**/*.test.js\" --exit",
"tdd": "cross-env NODE_ENV=test nyc mocha --watch \"test/spec/**/*.test.js\"",
"test:single": "cross-env NODE_ENV=test nyc mocha ",
"test:functional": "cross-env NODE_ENV=test node ./test-functional/index.js",
Expand Down
42 changes: 26 additions & 16 deletions src/client/components/test/context.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,26 @@ import styles from './test.css';

const cx = classNames.bind(styles);

const videoRegEx = /(?:mp4|webm)$/i;
const videoRegEx = /(mp4|webm)$/i;
const imgRegEx = /(?:png|jpe?g|gif)$/i;
const protocolRegEx = /^(?:(?:https?|ftp):\/\/)/i;
const urlRegEx = /^(?:(?:https?|ftp):\/\/)?(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,}))\.?)(?::\d{2,5})?(?:[/?#]\S*)?$/; // eslint-disable-line
const base64ImgRegEx = /^data:image\/([a-zA-Z0-9-_.])+;base64,([^"]*)$/i;
const base64VidRegEx = /^data:video\/(mp4|webm);base64,(?:[^"]*)$/i;

const isVideo = str => {
const getVideoType = str => {
if (!isString(str)) {
return false;
return undefined;
}

const hashIndex = str.indexOf('#');
return videoRegEx.test(hashIndex > 0 ? str.slice(0, hashIndex) : str);
}

const [, type] =
videoRegEx.exec(hashIndex > 0 ? str.slice(0, hashIndex) : str) ||
base64VidRegEx.exec(str) ||
[];
return type || undefined;
};

class TestContext extends Component {
static displayName = 'TestContext';
Expand All @@ -34,22 +40,25 @@ class TestContext extends Component {
]),
};

renderVideo = (ctx, title) => {
renderVideo = (ctx, title, type) => {
const isUrl = urlRegEx.test(ctx);
const hasProtocol = protocolRegEx.test(ctx);
const linkUrl = isUrl && !hasProtocol ? `http://${ctx}` : ctx;

return (
<video controls src={linkUrl} className={cx('video')}>
<video controls className={cx('video')}>
<source type={`video/${type}`} src={linkUrl} />
<track kind="captions" />
{title}
<a
href={linkUrl}
className={cx('video-link')}
rel="noopener noreferrer"
target="_blank">
{linkUrl}
</a>
{isUrl && (
<a
href={linkUrl}
className={cx('video-link')}
rel="noopener noreferrer"
target="_blank">
{linkUrl}
</a>
)}
</video>
);
};
Expand Down Expand Up @@ -89,8 +98,9 @@ class TestContext extends Component {

renderContextContent = (content, title, highlight = false) => {
// Videos
if (isVideo(content)) {
return this.renderVideo(content, title);
const videoType = getVideoType(content);
if (videoType) {
return this.renderVideo(content, title, videoType);
}

// Images
Expand Down
61 changes: 57 additions & 4 deletions test/spec/components/test/context.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ describe('<TestContext />', () => {
imgLink: wrapper.find('.test-image-link'),
video: wrapper.find('.test-video'),
videoLink: wrapper.find('.test-video-link'),
videoSource: wrapper.find('.test-video source'),
link: wrapper.find('.test-text-link'),
snippet: wrapper.find(CodeSnippet),
};
Expand Down Expand Up @@ -141,9 +142,9 @@ describe('<TestContext />', () => {
expect(img).to.have.lengthOf(1);
});

it('renders local video', () => {
it('renders local video - mp4', () => {
const context = '/testvideo.mp4';
const { wrapper, snippet, video } = getInstance({
const { wrapper, snippet, videoSource } = getInstance({
context: JSON.stringify(context),
className: 'test',
});
Expand All @@ -152,7 +153,23 @@ describe('<TestContext />', () => {
expect(wrapper)
.to.have.exactly(1)
.descendants('video');
expect(video).to.have.attr('src', '/testvideo.mp4');
expect(videoSource).to.have.attr('type', 'video/mp4');
expect(videoSource).to.have.attr('src', '/testvideo.mp4');
});

it('renders local video - webm', () => {
const context = '/testvideo.webm';
const { wrapper, snippet, videoSource } = getInstance({
context: JSON.stringify(context),
className: 'test',
});
expect(wrapper).to.have.className('test');
expect(snippet).to.have.lengthOf(0);
expect(wrapper)
.to.have.exactly(1)
.descendants('video');
expect(videoSource).to.have.attr('type', 'video/webm');
expect(videoSource).to.have.attr('src', '/testvideo.webm');
});

it('renders video url with protocol', () => {
Expand Down Expand Up @@ -195,7 +212,7 @@ describe('<TestContext />', () => {
);
});

it('renders image url without protocol', () => {
it('renders video url without protocol', () => {
const context = 'test.url.com/testvideo.mp4';
const { wrapper, snippet, videoLink } = getInstance({
context: JSON.stringify(context),
Expand All @@ -214,6 +231,42 @@ describe('<TestContext />', () => {
'http://test.url.com/testvideo.mp4'
);
});

it('renders base64 video - mp4', () => {
const context = 'data:video/mp4;base64,AAAAIGZ';
const { wrapper, snippet, video, videoSource } = getInstance({
context: JSON.stringify(context),
className: 'test',
});
expect(wrapper).to.have.className('test');
expect(snippet).to.have.lengthOf(0);
expect(wrapper)
.to.have.exactly(1)
.descendants('video');
expect(video)
.to.have.exactly(0)
.descendants('a');
expect(videoSource).to.have.attr('type', 'video/mp4');
expect(videoSource).to.have.attr('src', context);
});

it('renders base64 video - webm', () => {
const context = 'data:video/webm;base64,AAAAIGZ';
const { wrapper, snippet, video, videoSource } = getInstance({
context: JSON.stringify(context),
className: 'test',
});
expect(wrapper).to.have.className('test');
expect(snippet).to.have.lengthOf(0);
expect(wrapper)
.to.have.exactly(1)
.descendants('video');
expect(video)
.to.have.exactly(0)
.descendants('a');
expect(videoSource).to.have.attr('type', 'video/webm');
expect(videoSource).to.have.attr('src', context);
});
});

describe('when context is an object', () => {
Expand Down

0 comments on commit bbf3ad6

Please sign in to comment.