How load gulp task from file to another task - gulp-4

I have simply 'watchFiles' task which after file changed use task 'reload'. This 'reload' task is in separate file. How can I load this task to my 'watchFiles' task when I don't want this task in the same file?
// watchFiles task
gulp.task(watchFiles);
function watchFiles(cb) {
watch(src + '**/*.html', series('reload'));
cb();
}
// reload task in another file
gulp.task(reload);
function reload(cb) {
browserSync.reload();
cb();
}
// run from gulpfile
exports.watch = series('watchFiles');

I would do like this:
// watchFiles task file = watchfiles_task_file.js
const { reload } = require('./reload_task_file');
const { series, watch } = require('gulp');
const src = './';
function watchFiles(cb) {
watch(src + '**/*.html', series(reload));
cb();
}
exports.watchFiles = watchFiles;
// end watchfiles_task_file.js
// reload task in another file = reload_task_file.js
const browserSync = require('browser-sync').create();
function reload(cb) {
browserSync.reload();
cb();
}
exports.reload = reload;
// end reload_task_file.js
// gulpfile.js
const { watchFiles } = require('./watchfiles_task_file');
const { series } = require('gulp');
exports.watch = series(watchFiles);

Related

Cypress - How can I add assertion for downloaded file contains name that is dynamic?

In cypress, the xlsx file I am downloading always starts with lets say "ABC" and then some dynamic IDs like ABC86520837.xlsx. How can I verify and add assertion that if the file is downloaded successfully and also contains that dynamic name?
You'll need to create a task to search within file directory of your machine and then return a list of matching downloads to assert. You'll also need globby to make it easier.
In your plugins/index.js
async findFiles (mask) {
if (!mask) {
throw new Error('Missing a file mask to search')
}
console.log('searching for files %s', mask)
const list = await globby(mask)
if (!list.length) {
console.log('found no files')
return null
}
console.log('found %d files, first one %s', list.length, list[0])
return list[0]
},
In your spec file:
const downloadsFolder = Cypress.config('downloadsFolder')
const mask = `${downloadsFolder}/ABC*.xlsx`
cy.task('findFiles', mask).then((foundImage) => {
expect(foundImage).to.be.a('string')
cy.log(`found image ${foundImage}`)
})
Cypress example
Assuming you are running a recent version of Cypress,
Add a task to read the downloads folder in /cypress.config.js
const { defineConfig } = require('cypress')
const fs = require('fs')
module.exports = defineConfig({
e2e: {
setupNodeEvents(on, config) {
on('task', {
filesInDownload (folderName) {
return fs.readdirSync(folderName)
},
})
}
}
})
In the test
const downloadsFolder = Cypress.config('downloadsFolder')
cy.task('filesInDownload', downloadsFolder).then(files => {
const abcFile = files.find(file => file.startsWith('ABC'))
expect(abcFile).to.not.be.undefined
})
I recommend you set the downloadsFolder configuration, as this will remove files between test runs.

Read excel files in Cypress

I am new to Cypress. How to read data from excel files using Cypress? Searched in google but could not find useful answers.
In cypress you can create cypress task to read xlsx file with SheetJS library.
Usage
cypress\integration\read-xlsx.spec.js
context('Xlsx file', () => {
it('Read excel file', () => {
cy.task('readXlsx', { file: 'my-excel.xlsx', sheet: "Sheet1" }).then((rows) => {
expect(rows.length).to.equal(543)
// expect(rows[0]["column name"]).to.equal(11060)
})
})
})
Need to install xlsx
$ npm install xlsx
Create read excel fuction
cypress\plugins\read-xlsx.js
const fs = require('fs');
const XLSX = require('xlsx');
const read = ({file, sheet}) => {
const buf = fs.readFileSync(file);
const workbook = XLSX.read(buf, { type: 'buffer' });
const rows = XLSX.utils.sheet_to_json(workbook.Sheets[sheet]);
return rows
}
module.exports = {
read,
}
Use function as Cypress task (plugin)
cypress\plugins\index.js
const readXlsx = require('./read-xlsx')
module.exports = (on, config) => {
on('task', {
'readXlsx': readXlsx.read
})
}
Here is an instruction how to use excel as source for cypress tests https://medium.com/#you54f/dynamically-generate-data-in-cypress-from-csv-xlsx-7805961eff55
First you need to conver your xlsx file to json with Xlsx
import { writeFileSync } from "fs";
import * as XLSX from "xlsx";
try {
const workBook = XLSX.readFile("./testData/testData.xlsx");
const jsonData = XLSX.utils.sheet_to_json(workBook.Sheets.testData);
writeFileSync(
"./cypress/fixtures/testData.json",
JSON.stringify(jsonData, null, 4),
"utf-8"
);
} catch (e) {
throw Error(e);
}
Then import json file and loop over each row and use the data in the way you want. In this example it tries to log in to a system.
import { login } from "../support/pageObjects/login.page";
const testData = require("../fixtures/testData.json");
describe("Dynamically Generated Tests", () => {
testData.forEach((testDataRow: any) => {
const data = {
username: testDataRow.username,
password: testDataRow.password
};
context(`Generating a test for ${data.username}`, () => {
it("should fail to login for the specified details", () => {
login.visit();
login.username.type(data.username);
login.password.type(`${data.password}{enter}`);
login.errorMsg.contains("Your username is invalid!");
login.logOutButton.should("not.exist");
});
});
});
});
For me the first answer pretty much worked. But i had to make a small fix.
Use function as Cypress task (plugin)
cypress/plugins/index.js
const readXlsx = require('./read-xlsx')
module.exports = (on, config) => {
on('task', {
'readXlsx': readXlsx.read
})
}
when i used this code i got the below error in cypress.
CypressError
cy.task('log') failed with the following error:
The task 'log' was not handled in the plugins file. The following tasks are registered: readXlsx
and the below fix worked
const readXlsx = require('./read-xlsx')
module.exports = (on, config) => {
on('task', {
'readXlsx': readXlsx.read,
log (message) {
console.log(message)
return null
}
})
}

How can I fix gulp watch not watching files

I'm using gulp to watch file changes and compile my scss, But watch isn't tracking the file changes.
im using gulp-sass and the version is 4.0
const { src, dest, watch, series } = require('gulp');
const { sass } = require('gulp-sass');
function compileSass() {
return src('app/assets/scss/main.scss')
.pipe(sass())
.pipe(dest('app/css'));
}
function start() {
//compile and watch
watch('app/assets/scss/**/*.scss', { events: 'change' }, function(compileSass) {
// body omitted
compileSass();
});
}
exports.default = series(start);
Try:
function start() {
//compile and watch
watch('app/assets/scss/**/*.scss', { events: 'change' }, function(cb) {
// body omitted
compileSass();
cb();
})
}
cb is a callback function - just leave it as cb (it doesn't need to exist anywhere else) and is called last in the task.
Not sure why your task is not wrapped in gulp.task.
Try to paste this code in your gulpfile.js
gulpfile.js
const gulp = require('gulp');
const sass = require('gulp-sass'); // not { sass }
/** Transpile sass/scss to css */
gulp.task('compile-sass', () => {
return gulp.src('app/assets/scss/main.scss')
.pipe(sass())
.pipe(gulp.dest('app/css'));
});
/** Run the compile-sass task then set a watchers to app/assets/scss/**/*.scss */
gulp.task('watch', gulp.series(
'compile-sass',
(done) => {
gulp.watch('app/assets/scss/**/*.scss')
.on('change', gulp.series('compile-sass'))
done()
},
));
/** Default task */
gulp.task('default', gulp.series('watch'));
Now you can run it using gulp in your terminal.

Unable to setup gulp sass with bundling and minification

I am having troubling running sass and minification together. Some times the minification task starts before the sass task has finished.
When I run the separately they work fine.
Here is my gulp file...
/// <binding />
"use strict";
var gulp = require("gulp"),
concat = require("gulp-concat"),
cssmin = require("gulp-cssmin"),
merge = require("merge-stream"),
del = require("del"),
bundleconfig = require("./bundleconfig.json"),
runSequence = require('run-sequence');
var sass = require('gulp-sass');
var browserify = require('browserify');
var babelify = require('babelify');
var source = require('vinyl-source-stream');
var webroot = "./wwwroot/";
var paths = {
scss: webroot + "sass/**/*.scss",
scssDest: webroot + "css/"
};
// 1. react
gulp.task('react', function () {
return browserify({ entries: './wwwroot/clientapp/root', extensions: ['.jsx', '.js'], debug: true })
.transform('babelify', { presets: ['es2015', 'react'] })
.bundle()
.pipe(source('index.js'))
.pipe(gulp.dest('./wwwroot/'));
});
// 2. sass
gulp.task('compile:sass', function () {
gulp.src(paths.scss)
.pipe(sass())
.pipe(gulp.dest(paths.scssDest));
});
gulp.task("sass", ["compile:sass"]);
function getBundles(regexPattern) {
return bundleconfig.filter(function (bundle) {
return regexPattern.test(bundle.outputFileName);
});
}
gulp.task("css", function () {
var tasks = getBundles(/\.css$/).map(function (bundle) {
return gulp.src(bundle.inputFiles, { base: "." })
.pipe(concat(bundle.outputFileName))
.pipe(cssmin())
.pipe(gulp.dest("."));
});
return merge(tasks);
});
gulp.task("clean", function () {
return del(['wwwroot/css/*', 'wwwroot/index.js']);
});
gulp.task("default", ["clean", "sass", "react", "css"]);
It looks like you are assuming that these tasks are run in series:
gulp.task("default", ["clean", "sass", "react", "css"]);
They do not, from gulp.task documentation:
Note: The tasks will run in parallel (all at once), so don't assume that the tasks will start/finish in order.
There are a number of ways to fix that and there should be a few questions here on the subject.
You can use run-sequence, use gulp4.0 which has series and parallel functions (but is still technically in beta) or make some task like your 'react' task dependent on the 'sass' and 'css" tasks having finished.
So try :
gulp.task('react', ['css'], function () { ...
gulp.task("css", ['sass'], function () { ...
gulp.task('compile:sass', ['clean'], function () { ...
and now simply
gulp.task("default", ["react"]);
will fire them off in the correct order.
Although I suppose 'clean' doesn't necessarily have to run first. run-sequence does help to make the order of things much more obvious. If you can I would suggest looking into gulp4.

Gulp with spritesmith and sass compilation

I have the following issue in my gulp build. In one task, I create sprite files for each of my folder and then I run a task compiling sass files which uses spritesmith sass files.
I got the following error :
Error: File to import not found or unreadable: sprites/x
NB: x is the name of my folder in ASSETS_SPRITE_SRC
Here is my spritesmith task
export = function buildAssets(gulp, plugins, option) {
return function () {
var folders = getFolders(ASSETS_SPRITE_SRC);
folders.map(function(folder) {
var spriteData = gulp.src(path.join(ASSETS_SPRITE_SRC, folder, '/*.*'))
.pipe(plugins.spritesmith({
imgName: folder + '.png',
cssName: folder + '.scss'
}));
spriteData.img.pipe(gulp.dest(ASSETS_SPRITE_DEST));
spriteData.css.pipe(gulp.dest(STYLE_SRC + '/sprites'));
});
return gulp.dest(STYLE_SRC + '/sprites');
};
}
function getFolders(dir) {
return fs.readdirSync(dir)
.filter(function(file) {
return fs.statSync(path.join(dir, file)).isDirectory();
});
}
inspired from: https://github.com/gulpjs/gulp/blob/master/docs/recipes/running-task-steps-per-folder.md
And here is my sass task
export = function buildSassDev(gulp, plugins, option) {
return function () {
return gulp.src(join(STYLE_SRC, '**', '*.scss'))
.pipe(plugins.sass().on('error', plugins.sass.logError))
.pipe(gulp.dest(CSS_DEST));
}; }
I run buildAssets first, then buildSassDev.
What I'm wrong about ?
I finally found what I was wrong about. I needed to merge both spriteData.img.pipe and spriteData.css.pipe to be sure they were both ok.
Here is the right code:
export = function buildAssets(gulp, plugins, option) {
return function () {
var folders = getFolders(ASSETS_SPRITE_SRC);
var tasks = folders.map(function (folder) {
var spriteData = gulp.src(path.join(ASSETS_SPRITE_SRC, folder, '/*.*'))
.pipe(plugins.spritesmith({
imgName: folder + '.png',
cssName: folder + '.scss'
}));
var imgStream = spriteData.img.pipe(gulp.dest(ASSETS_SPRITE_DEST));
var cssStream = spriteData.css.pipe(gulp.dest(STYLE_SRC + '/sprites'));
return merge(imgStream, cssStream);
});
return merge(tasks);
};
}

Resources