epegzz/sass-vars-loader

View on GitHub
src/sassVarsLoader.test.js

Summary

Maintainability
A
0 mins
Test Coverage
const path = require('path')
const sassVarsLoader = require('./sassVarsLoader')

const mockSassFileContents = `sassFileContents`
let result, error, mockOptions
const loaderContext = {
  cacheable: jest.fn(),
  addDependency: jest.fn(),
  resolve: jest.fn((context, file, callback) => {
    callback(null, file)
  }),
}

jest.mock('loader-utils', () => ({
  getOptions: () => mockOptions,
}))

describe('With vars from webpack config', () => {
  beforeAll(async () => {
    await setup({
      vars: {
        value1FromWebpack: 'foo',
        nested: {
          works: {
            veryWell: true,
            withoutProblems: 'indeed',
          },
        },
      },
    })
  })
  expectCorrectResult()
  expectMarksItselfAsCacheable()
})

describe('With vars from files', () => {
  beforeAll(async () => {
    await setup({
      files: [
        path.resolve(__dirname, '__mocks__/jsonVars1.json'),
        path.resolve(__dirname, '__mocks__/jsVars1.js'),
        path.resolve(__dirname, '__mocks__/tsVars1.ts'),
        path.resolve(__dirname, '__mocks__/jsonVars2.json'),
      ],
    })
  })
  expectCorrectResult()
  expectMarksItselfAsCacheable()
  expectWatchesFilesForChanges()
})

describe('With vars from JSON, JS and config', () => {
  beforeAll(async () => {
    await setup({
      vars: {
        loadingOrderTest3: 'fromConfig',
      },
      files: [
        path.resolve(__dirname, '__mocks__/jsonVars1.json'),
        path.resolve(__dirname, '__mocks__/jsVars1.js'),
        path.resolve(__dirname, '__mocks__/tsVars1.ts'),
      ],
    })
  })
  expectCorrectResult()
})

describe('Without options', () => {
  beforeAll(async () => {
    await setup()
  })
  expectCorrectResult()
  expectMarksItselfAsCacheable()
})

describe('With sass syntax', () => {
  beforeAll(async () => {
    await setup({
      syntax: 'sass',
      vars: {
        value1FromWebpack: 'foo',
        nested: {
          works: {
            veryWell: true,
            withoutProblems: 'indeed',
          },
        },
      },
    })
  })
  expectCorrectResult()
})

describe('With invalid file', () => {
  beforeAll(async () => {
    await setup({
      syntax: 'sass',
      files: ['~invalid~'],
    })
  })
  expectError(`Invalid file: "~invalid~". Consider using "path.resolve" in your config.`)
})

describe('With single post-processing', () => {
  beforeAll(async () => {
    await setup({
      transformKeys: key => `transformed-${key}`,
      vars: {
        'transformed-valueToTransform': 'foo',
        'transformed-nested': {
          'transformed-works': {
            'transformed-Complete': true,
            'transformed-veryWellResult': true,
            'transformed-withoutProblems': 'indeed',
          },
        },
      },
    })
  })
  expectCorrectResult()
  expectMarksItselfAsCacheable()
})

describe('With multi post-processing', () => {
  beforeAll(async () => {
    await setup({
      transformKeys: [key => `transformed-${key}`, key => key.toUpperCase()],
      vars: {
        'TRANSFORMED-VALUETOTRANSFORM': 'foo',
        'TRANSFORMED-NESTED': {
          'TRANSFORMED-WORKS': {
            'TRANSFORMED-COMPLETE': true,
            'TRANSFORMED-VERYWELLRESULT': true,
            'TRANSFORMED-WITHOUTPROBLEMS': 'indeed',
          },
        },
      },
    })
  })
  expectCorrectResult()
  expectMarksItselfAsCacheable()
})

async function setup(options) {
  result = null
  error = null
  mockOptions = options
  loaderContext.addDependency.mockClear()
  loaderContext.cacheable.mockClear()
  loaderContext.async = () => (err, res) => {
    error = err
    result = res
  }
  await sassVarsLoader.call(loaderContext, mockSassFileContents)
}

function expectCorrectResult() {
  it('Returns expected Sass contents', () => {
    expect(result).toMatchSnapshot()
  })
}

function expectError(message) {
  it('Returns an error', () => {
    expect(error && error.message).toEqual(message)
  })
}

function expectMarksItselfAsCacheable() {
  it('Marks itself as cacheable', () => {
    expect(loaderContext.cacheable).toHaveBeenCalled()
  })
}

function expectWatchesFilesForChanges() {
  it('Watches files for changes', () => {
    const { files } = mockOptions
    expect(loaderContext.addDependency).toHaveBeenCalledTimes(files.length)
  })
}