or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

css-output-testing.mderror-handling.mdindex.mdjavascript-integration.mdtest-structure.mdvalue-assertions.md

javascript-integration.mddocs/

0

# JavaScript Integration

1

2

Complete integration with JavaScript/TypeScript test runners, providing automated CSS parsing, test result reporting, and seamless workflow integration with Mocha, Jest, and other test frameworks.

3

4

## Capabilities

5

6

### Main Integration Function

7

8

Compiles Sass files and runs tests through JavaScript test runners with automated result parsing.

9

10

```typescript { .api }

11

/**

12

* Compile Sass tests and run them through JavaScript test runners

13

* @param trueOptions - Configuration object with test runner functions and options

14

* @param src - Path to Sass file or Sass source string

15

* @param sassOptions - Options passed to Sass compiler

16

*/

17

function runSass(

18

trueOptions: TrueOptions,

19

src: string,

20

sassOptions?: any

21

): void;

22

23

interface TrueOptions {

24

/** Describe function from your test runner (e.g., Mocha's describe) */

25

describe: (description: string, fn: () => void) => void;

26

/** It function from your test runner (e.g., Mocha's it) */

27

it: (description: string, fn: () => void) => void;

28

/** Sass compiler instance or package name ('sass', 'sass-embedded') */

29

sass?: any | string;

30

/** Whether src parameter is a file path or source string */

31

sourceType?: 'path' | 'string';

32

/** Number of context lines to show in error messages */

33

contextLines?: number;

34

}

35

```

36

37

**Basic Usage Examples:**

38

39

```javascript

40

// Basic Mocha integration

41

const path = require('node:path');

42

const sassTrue = require('sass-true');

43

44

const sassFile = path.join(__dirname, 'test.scss');

45

sassTrue.runSass({ describe, it }, sassFile);

46

```

47

48

```javascript

49

// Jest integration

50

const path = require('node:path');

51

const sassTrue = require('sass-true');

52

53

describe('Sass Tests', () => {

54

const sassFile = path.join(__dirname, 'sass/test.scss');

55

sassTrue.runSass({ describe, it }, sassFile);

56

});

57

```

58

59

```typescript

60

// TypeScript with explicit types

61

import * as sassTrue from 'sass-true';

62

import * as path from 'node:path';

63

64

const sassFile = path.join(__dirname, 'test.scss');

65

sassTrue.runSass({ describe, it }, sassFile);

66

```

67

68

### Advanced Configuration

69

70

```javascript

71

const path = require('node:path');

72

const sassTrue = require('sass-true');

73

74

// With custom Sass compiler

75

sassTrue.runSass(

76

{

77

describe,

78

it,

79

sass: 'sass-embedded', // Specify compiler

80

contextLines: 15 // More error context

81

},

82

path.join(__dirname, 'test.scss'),

83

{

84

// Sass options

85

loadPaths: ['./styles', './node_modules'],

86

style: 'expanded', // Must be 'expanded', not 'compressed'

87

sourceMap: false

88

}

89

);

90

91

// Using source string instead of file

92

const sassSource = `

93

@use 'true' as *;

94

@include test('String source test') {

95

@include assert-equal(1 + 1, 2);

96

}

97

`;

98

99

sassTrue.runSass(

100

{

101

describe,

102

it,

103

sourceType: 'string' // Indicate source is a string

104

},

105

sassSource

106

);

107

```

108

109

### Custom Importers

110

111

For projects using custom import patterns (like tilde notation):

112

113

```javascript

114

const path = require('node:path');

115

const { pathToFileURL } = require('node:url');

116

const sassTrue = require('sass-true');

117

118

const importers = [

119

{

120

findFileUrl(url) {

121

if (!url.startsWith('~')) {

122

return null;

123

}

124

return new URL(

125

pathToFileURL(path.resolve('node_modules', url.substring(1)))

126

);

127

},

128

},

129

];

130

131

const sassFile = path.join(__dirname, 'test.scss');

132

sassTrue.runSass({ describe, it }, sassFile, { importers });

133

```

134

135

## Test Result Types

136

137

### Core Data Structures

138

139

The JavaScript integration parses CSS output into structured test results:

140

141

```typescript { .api }

142

interface Assertion {

143

/** Description of what is being asserted */

144

description: string;

145

/** Type of assertion (equal, output, contains, etc.) */

146

assertionType?: string;

147

/** Actual output from the test */

148

output?: string;

149

/** Expected output for comparison */

150

expected?: string;

151

/** Additional details about the assertion */

152

details?: string;

153

/** Whether the assertion passed */

154

passed?: boolean;

155

/** Additional assertion-specific properties */

156

[key: string]: boolean | string | undefined;

157

}

158

159

interface Test {

160

/** Name/description of the test */

161

test: string;

162

/** Array of assertions within this test */

163

assertions: Assertion[];

164

}

165

166

interface Module {

167

/** Name/description of the module */

168

module: string;

169

/** Tests directly within this module */

170

tests?: Test[];

171

/** Nested sub-modules */

172

modules?: Module[];

173

}

174

```

175

176

### CSS Output Parsing

177

178

```typescript { .api }

179

/**

180

* Parse Sass-compiled CSS output containing True test results

181

* @param rawCss - CSS string output from Sass compilation

182

* @param contextLines - Number of context lines to show in error messages (default: 10)

183

* @returns Array of parsed test modules with their results

184

*/

185

function parse(rawCss: string, contextLines?: number): Module[];

186

```

187

188

**Usage Example:**

189

190

```javascript

191

const sass = require('sass');

192

const sassTrue = require('sass-true');

193

const path = require('node:path');

194

195

// Compile Sass file manually

196

const sassFile = path.join(__dirname, 'test.scss');

197

const result = sass.compile(sassFile);

198

199

// Parse the CSS output for test results

200

const modules = sassTrue.parse(result.css);

201

202

// Process the parsed results

203

modules.forEach(module => {

204

console.log(`Module: ${module.module}`);

205

module.tests?.forEach(test => {

206

console.log(` Test: ${test.test}`);

207

test.assertions.forEach(assertion => {

208

const status = assertion.passed ? 'PASS' : 'FAIL';

209

console.log(` ${status}: ${assertion.description}`);

210

});

211

});

212

});

213

```

214

215

### Failure Message Formatting

216

217

```typescript { .api }

218

/**

219

* Format detailed failure messages with diffs for failed assertions

220

* @param assertion - The failed assertion object

221

* @returns Formatted error message with visual diff

222

*/

223

function formatFailureMessage(assertion: Assertion): string;

224

```

225

226

**Usage Example:**

227

228

```javascript

229

// This is handled automatically by runSass, but you can use it manually:

230

const sassTrue = require('sass-true');

231

232

const failedAssertion = {

233

description: 'Should match expected output',

234

assertionType: 'equal',

235

output: 'color: red;',

236

expected: 'color: blue;',

237

passed: false

238

};

239

240

console.log(sassTrue.formatFailureMessage(failedAssertion));

241

// Outputs formatted diff showing expected vs actual

242

```

243

244

## Framework-Specific Setup

245

246

### Mocha Integration

247

248

```javascript

249

// test/sass.test.js

250

const path = require('node:path');

251

const sassTrue = require('sass-true');

252

253

// Single test file

254

const sassFile = path.join(__dirname, 'sass/test.scss');

255

sassTrue.runSass({ describe, it }, sassFile);

256

257

// Multiple test files

258

const testFiles = [

259

'sass/utilities.test.scss',

260

'sass/components.test.scss',

261

'sass/mixins.test.scss'

262

];

263

264

testFiles.forEach(file => {

265

const sassFile = path.join(__dirname, file);

266

sassTrue.runSass({ describe, it }, sassFile);

267

});

268

```

269

270

### Jest Integration

271

272

```javascript

273

// test/sass.test.js

274

const path = require('node:path');

275

const sassTrue = require('sass-true');

276

277

describe('Sass Tests', () => {

278

const sassFile = path.join(__dirname, 'sass/test.scss');

279

sassTrue.runSass({ describe, it }, sassFile);

280

});

281

```

282

283

**Jest Configuration:**

284

285

```json

286

// jest.config.js

287

module.exports = {

288

testEnvironment: 'jest-environment-node-single-context',

289

moduleFileExtensions: ['js', 'json', 'scss'],

290

// Other Jest config...

291

};

292

```

293

294

### Other Test Runners

295

296

Any test runner with `describe` and `it` functions can be used:

297

298

```javascript

299

// Using AVA (adapted)

300

const test = require('ava');

301

const sassTrue = require('sass-true');

302

303

// Adapter for AVA

304

const avaDescribe = (name, fn) => {

305

// AVA doesn't have describe, so we just run the function

306

fn();

307

};

308

309

const avaIt = (name, fn) => {

310

test(name, t => {

311

try {

312

fn();

313

t.pass();

314

} catch (error) {

315

t.fail(error.message);

316

}

317

});

318

};

319

320

sassTrue.runSass({

321

describe: avaDescribe,

322

it: avaIt

323

}, './test.scss');

324

```

325

326

## Advanced Usage

327

328

### Error Handling and Debugging

329

330

```javascript

331

const sassTrue = require('sass-true');

332

333

try {

334

sassTrue.runSass({ describe, it }, './test.scss', {

335

// More context lines for debugging

336

contextLines: 20

337

});

338

} catch (error) {

339

console.error('Sass compilation failed:', error.message);

340

341

if (error.message.includes('Context')) {

342

console.log('Check your Sass syntax and imports');

343

}

344

}

345

```

346

347

### Multiple Sass Compilers

348

349

```javascript

350

// Test with different Sass implementations

351

const configs = [

352

{ sass: 'sass', name: 'Dart Sass' },

353

{ sass: 'sass-embedded', name: 'Embedded Dart Sass' }

354

];

355

356

configs.forEach(config => {

357

describe(`Sass Tests with ${config.name}`, () => {

358

sassTrue.runSass(

359

{ describe, it, sass: config.sass },

360

'./test.scss'

361

);

362

});

363

});

364

```

365

366

### CSS Output Parsing

367

368

The JavaScript integration automatically parses special CSS comments generated by Sass True:

369

370

```scss

371

// This Sass test:

372

@include test('Example test') {

373

@include assert-equal(1 + 1, 2);

374

}

375

376

// Generates CSS comments like:

377

/* # Module: Example Tests */

378

/* ## Test: Example test */

379

/* PASS: assert-equal(1 + 1, 2) */

380

```

381

382

The JavaScript parser reads these comments and converts them into test runner calls.

383

384

### Integration with CI/CD

385

386

```javascript

387

// test/sass.test.js for CI

388

const path = require('node:path');

389

const sassTrue = require('sass-true');

390

391

// Ensure tests fail CI on assertion failures

392

process.on('unhandledRejection', (error) => {

393

console.error('Unhandled promise rejection:', error);

394

process.exit(1);

395

});

396

397

const sassFile = path.join(__dirname, 'sass/test.scss');

398

sassTrue.runSass({ describe, it }, sassFile);

399

```

400

401

## Sass File Requirements

402

403

Your Sass test files should include True and define tests:

404

405

```scss

406

// test/sass/test.scss

407

@use 'true' as *;

408

409

@include describe('My Component') {

410

@include it('should have correct default styles') {

411

@include assert {

412

@include output {

413

@include my-component;

414

}

415

@include expect {

416

display: block;

417

padding: 1rem;

418

}

419

}

420

}

421

}

422

423

// Don't forget the report!

424

@include report;

425

```

426

427

## Troubleshooting

428

429

### Common Issues

430

431

1. **"Cannot find Dart Sass dependency"**

432

```bash

433

npm install --save-dev sass-embedded

434

# or

435

npm install --save-dev sass

436

```

437

438

2. **"compressed style not supported"**

439

```javascript

440

// Don't use compressed style

441

sassTrue.runSass({ describe, it }, file, {

442

style: 'expanded' // Use expanded (default)

443

});

444

```

445

446

3. **Jest environment issues**

447

```json

448

{

449

"testEnvironment": "jest-environment-node-single-context"

450

}

451

```

452

453

4. **Import resolution issues**

454

```javascript

455

sassTrue.runSass({ describe, it }, file, {

456

loadPaths: ['./sass', './node_modules'],

457

importers: [/* custom importers */]

458

});

459

```