Best Python code snippet using avocado_python
AudioPlayer.js
Source:AudioPlayer.js  
1import { AudioPlayer } from "../lib/AudioPlayer.js";2import { Color } from "../lib/Color.js";3class ColorToneEventListenerStub {4  constructor() {5    this.notifiedThatToneSeriesEnded_ = false;6    this.notifiedThatRedToneStarted_ = false;7    this.notifiedThatRedToneEnded_ = false;8    this.notifiedThatYellowToneStarted_ = false;9    this.notifiedThatYellowToneEnded_ = false;10    this.notifiedThatGreenToneStarted_ = false;11    this.notifiedThatGreenToneEnded_ = false;12    this.notifiedThatBlueToneStarted_ = false;13    this.notifiedThatBlueToneEnded_ = false;14    this.notifiedThatCorrectBlueToneStarted_ = false;15    this.notifiedThatCorrectBlueToneEnded_ = false;16    this.notifiedThatIncorrectBlueToneStarted_ = false;17    this.notifiedThatIncorrectBlueToneEnded_ = false;18  }19  notifiedThatIncorrectBlueToneEnded() {20    return this.notifiedThatIncorrectBlueToneEnded_;21  }22  notifyThatIncorrectBlueToneEnded() {23    this.notifiedThatIncorrectBlueToneEnded_ = true;24  }25  notifiedThatIncorrectBlueToneStarted() {26    return this.notifiedThatIncorrectBlueToneStarted_;27  }28  notifyThatIncorrectBlueToneStarted() {29    this.notifiedThatIncorrectBlueToneStarted_ = true;30  }31  notifiedThatCorrectBlueToneEnded() {32    return this.notifiedThatCorrectBlueToneEnded_;33  }34  notifyThatCorrectBlueToneEnded() {35    this.notifiedThatCorrectBlueToneEnded_ = true;36  }37  notifiedThatCorrectBlueToneStarted() {38    return this.notifiedThatCorrectBlueToneStarted_;39  }40  notifyThatCorrectBlueToneStarted() {41    this.notifiedThatCorrectBlueToneStarted_ = true;42  }43  notifiedThatRedToneStarted() {44    return this.notifiedThatRedToneStarted_;45  }46  notifyThatRedToneStarted() {47    this.notifiedThatRedToneStarted_ = true;48  }49  notifiedThatRedToneEnded() {50    return this.notifiedThatRedToneEnded_;51  }52  notifyThatRedToneEnded() {53    this.notifiedThatRedToneEnded_ = true;54  }55  notifiedThatBlueToneStarted() {56    return this.notifiedThatBlueToneStarted_;57  }58  notifyThatBlueToneStarted() {59    this.notifiedThatBlueToneStarted_ = true;60  }61  notifiedThatBlueToneEnded() {62    return this.notifiedThatBlueToneEnded_;63  }64  notifyThatBlueToneEnded() {65    this.notifiedThatBlueToneEnded_ = true;66  }67  notifiedThatGreenToneStarted() {68    return this.notifiedThatGreenToneStarted_;69  }70  notifyThatGreenToneStarted() {71    this.notifiedThatGreenToneStarted_ = true;72  }73  notifiedThatGreenToneEnded() {74    return this.notifiedThatGreenToneEnded_;75  }76  notifyThatGreenToneEnded() {77    this.notifiedThatGreenToneEnded_ = true;78  }79  notifiedThatYellowToneStarted() {80    return this.notifiedThatYellowToneStarted_;81  }82  notifyThatYellowToneStarted() {83    this.notifiedThatYellowToneStarted_ = true;84  }85  notifiedThatYellowToneEnded() {86    return this.notifiedThatYellowToneEnded_;87  }88  notifyThatYellowToneEnded() {89    this.notifiedThatYellowToneEnded_ = true;90  }91  notifiedThatToneSeriesEnded() {92    return this.notifiedThatToneSeriesEnded_;93  }94  notifyThatToneSeriesEnded() {95    this.notifiedThatToneSeriesEnded_ = true;96  }97}98function scheduledTone(startTimeSeconds, stopTimeSeconds, frequencyHz) {99  return {100    startTimeSeconds,101    stopTimeSeconds,102    frequencyHz,103  };104}105class AudioEnvironmentStub {106  constructor() {107    this.scheduledTones_ = [];108    this.scheduledToneOnEnds = [];109  }110  setCurrentTimeSeconds(x) {111    this.currentTimeSeconds_ = x;112  }113  currentTimeSeconds() {114    return this.currentTimeSeconds_;115  }116  scheduleTone(startTimeSeconds, stopTimeSeconds, frequencyHz, onEnd) {117    this.scheduledTones_.push(118      scheduledTone(startTimeSeconds, stopTimeSeconds, frequencyHz)119    );120    this.scheduledToneOnEnds.push(onEnd);121  }122  scheduledTones() {123    return this.scheduledTones_;124  }125  endNextTone() {126    const onEnd = this.scheduledToneOnEnds.shift();127    onEnd();128  }129}130function play(131  player,132  toneColors,133  toneDurationMilliseconds,134  toneOffsetToNextOnsetDurationMilliseconds135) {136  player.play(137    toneColors,138    toneDurationMilliseconds,139    toneOffsetToNextOnsetDurationMilliseconds140  );141}142function playCorrectRedTone(player, toneDurationMilliseconds) {143  player.playCorrectRedTone(toneDurationMilliseconds);144}145function playCorrectBlueTone(player, toneDurationMilliseconds) {146  player.playCorrectBlueTone(toneDurationMilliseconds);147}148function playCorrectGreenTone(player, toneDurationMilliseconds) {149  player.playCorrectGreenTone(toneDurationMilliseconds);150}151function playCorrectYellowTone(player, toneDurationMilliseconds) {152  player.playCorrectYellowTone(toneDurationMilliseconds);153}154function playIncorrectBlueTone(player, toneDurationMilliseconds) {155  player.playIncorrectBlueTone(toneDurationMilliseconds);156}157function setPlayDelaySeconds(player, x) {158  player.setPlayDelaySeconds(x);159}160function setToneSeriesDelaySeconds(player, x) {161  player.setToneSeriesDelaySeconds(x);162}163function setCurrentTimeSeconds(audioEnvironment, x) {164  audioEnvironment.setCurrentTimeSeconds(x);165}166function scheduledTones(audioEnvironment) {167  return audioEnvironment.scheduledTones();168}169function endNextTone(audioEnvironment) {170  audioEnvironment.endNextTone();171}172function notifiedThatRedToneStarted(listener) {173  return listener.notifiedThatRedToneStarted();174}175function notifiedThatRedToneEnded(listener) {176  return listener.notifiedThatRedToneEnded();177}178function notifiedThatGreenToneStarted(listener) {179  return listener.notifiedThatGreenToneStarted();180}181function notifiedThatGreenToneEnded(listener) {182  return listener.notifiedThatGreenToneEnded();183}184function notifiedThatYellowToneStarted(listener) {185  return listener.notifiedThatYellowToneStarted();186}187function notifiedThatYellowToneEnded(listener) {188  return listener.notifiedThatYellowToneEnded();189}190function notifiedThatBlueToneStarted(listener) {191  return listener.notifiedThatBlueToneStarted();192}193function notifiedThatBlueToneEnded(listener) {194  return listener.notifiedThatBlueToneEnded();195}196function notifiedThatToneSeriesEnded(listener) {197  return listener.notifiedThatToneSeriesEnded();198}199function notifiedThatCorrectBlueToneStarted(listener) {200  return listener.notifiedThatCorrectBlueToneStarted();201}202function notifiedThatCorrectBlueToneEnded(listener) {203  return listener.notifiedThatCorrectBlueToneEnded();204}205function notifiedThatIncorrectBlueToneStarted(listener) {206  return listener.notifiedThatIncorrectBlueToneStarted();207}208function notifiedThatIncorrectBlueToneEnded(listener) {209  return listener.notifiedThatIncorrectBlueToneEnded();210}211function playing(player) {212  return player.playing();213}214function expectTrue(b) {215  expect(b).toBeTrue();216}217function expectFalse(b) {218  expect(b).toBeFalse();219}220function expectScheduledTonesContains(221  audioEnvironment,222  startTimeSeconds,223  stopTimeSeconds,224  frequencyHz225) {226  expect(scheduledTones(audioEnvironment)).toContain(227    scheduledTone(startTimeSeconds, stopTimeSeconds, frequencyHz)228  );229}230describe("AudioPlayer", () => {231  beforeEach(function () {232    this.audioEnvironment = new AudioEnvironmentStub();233    this.audioEnvironment = new AudioEnvironmentStub();234    this.player = new AudioPlayer(235      this.audioEnvironment,236      new Map([237        [Color.blue, 1],238        [Color.red, 2],239        [Color.yellow, 3],240        [Color.green, 4],241      ]),242      9243    );244  });245  it("should schedule silent tone before playing correct red tone", function () {246    setPlayDelaySeconds(this.player, 5);247    setCurrentTimeSeconds(this.audioEnvironment, 6);248    playCorrectRedTone(this.player, 7000);249    expectScheduledTonesContains(this.audioEnvironment, 6, 5 + 6, 0);250  });251  it("should schedule correct red tone", function () {252    setPlayDelaySeconds(this.player, 5);253    setCurrentTimeSeconds(this.audioEnvironment, 6);254    playCorrectRedTone(this.player, 7000);255    expectScheduledTonesContains(this.audioEnvironment, 5 + 6, 5 + 6 + 7, 2);256  });257  it("should schedule silent tone before playing correct yellow tone", function () {258    setPlayDelaySeconds(this.player, 5);259    setCurrentTimeSeconds(this.audioEnvironment, 6);260    playCorrectYellowTone(this.player, 7000);261    expectScheduledTonesContains(this.audioEnvironment, 6, 5 + 6, 0);262  });263  it("should schedule correct yellow tone", function () {264    setPlayDelaySeconds(this.player, 5);265    setCurrentTimeSeconds(this.audioEnvironment, 6);266    playCorrectYellowTone(this.player, 7000);267    expectScheduledTonesContains(this.audioEnvironment, 5 + 6, 5 + 6 + 7, 3);268  });269  it("should schedule silent tone before playing correct green tone", function () {270    setPlayDelaySeconds(this.player, 5);271    setCurrentTimeSeconds(this.audioEnvironment, 6);272    playCorrectGreenTone(this.player, 7000);273    expectScheduledTonesContains(this.audioEnvironment, 6, 5 + 6, 0);274  });275  it("should schedule correct green tone", function () {276    setPlayDelaySeconds(this.player, 5);277    setCurrentTimeSeconds(this.audioEnvironment, 6);278    playCorrectGreenTone(this.player, 7000);279    expectScheduledTonesContains(this.audioEnvironment, 5 + 6, 5 + 6 + 7, 4);280  });281  it("should schedule silent tone before playing correct blue tone", function () {282    setPlayDelaySeconds(this.player, 5);283    setCurrentTimeSeconds(this.audioEnvironment, 6);284    playCorrectBlueTone(this.player, 7000);285    expectScheduledTonesContains(this.audioEnvironment, 6, 5 + 6, 0);286  });287  it("should schedule correct blue tone", function () {288    setPlayDelaySeconds(this.player, 5);289    setCurrentTimeSeconds(this.audioEnvironment, 6);290    playCorrectBlueTone(this.player, 7000);291    expectScheduledTonesContains(this.audioEnvironment, 5 + 6, 5 + 6 + 7, 1);292  });293  it("should schedule silent tone before playing incorrect blue tone", function () {294    setPlayDelaySeconds(this.player, 5);295    setCurrentTimeSeconds(this.audioEnvironment, 6);296    playIncorrectBlueTone(this.player, 7000);297    expectScheduledTonesContains(this.audioEnvironment, 6, 5 + 6, 0);298  });299  it("should schedule incorrect blue tone", function () {300    setPlayDelaySeconds(this.player, 5);301    setCurrentTimeSeconds(this.audioEnvironment, 6);302    playIncorrectBlueTone(this.player, 7000);303    expectScheduledTonesContains(this.audioEnvironment, 5 + 6, 5 + 6 + 7, 9);304  });305  it("should schedule silent tone before first color tone on play", function () {306    setPlayDelaySeconds(this.player, 5);307    setCurrentTimeSeconds(this.audioEnvironment, 6);308    setToneSeriesDelaySeconds(this.player, 9);309    play(310      this.player,311      [Color.red, Color.green, Color.blue, Color.yellow],312      7000,313      8000314    );315    expectScheduledTonesContains(this.audioEnvironment, 6, 5 + 6 + 9, 0);316  });317  it("should schedule first color tone on play", function () {318    setPlayDelaySeconds(this.player, 5);319    setCurrentTimeSeconds(this.audioEnvironment, 6);320    play(321      this.player,322      [Color.red, Color.green, Color.blue, Color.yellow],323      7000,324      8000325    );326    expectScheduledTonesContains(this.audioEnvironment, 5 + 6, 5 + 6 + 7, 2);327  });328  it("should schedule second silent tone after first completes", function () {329    setPlayDelaySeconds(this.player, 5);330    setCurrentTimeSeconds(this.audioEnvironment, 6);331    play(332      this.player,333      [Color.red, Color.green, Color.blue, Color.yellow],334      7000,335      8000336    );337    endNextTone(this.audioEnvironment);338    expectScheduledTonesContains(339      this.audioEnvironment,340      5 + 6 + 7,341      5 + 6 + 7 + 8,342      0343    );344  });345  it("should schedule second color tone after first completes", function () {346    setPlayDelaySeconds(this.player, 5);347    setCurrentTimeSeconds(this.audioEnvironment, 6);348    play(349      this.player,350      [Color.red, Color.green, Color.blue, Color.yellow],351      7000,352      8000353    );354    endNextTone(this.audioEnvironment);355    endNextTone(this.audioEnvironment);356    expectScheduledTonesContains(357      this.audioEnvironment,358      5 + 6 + 7 + 8,359      5 + 6 + 7 + 8 + 7,360      4361    );362  });363  it("should not schedule additional color tone after last completes", function () {364    setPlayDelaySeconds(this.player, 5);365    setCurrentTimeSeconds(this.audioEnvironment, 6);366    play(367      this.player,368      [Color.red, Color.green, Color.blue, Color.yellow],369      7000,370      8000371    );372    endNextTone(this.audioEnvironment);373    endNextTone(this.audioEnvironment);374    endNextTone(this.audioEnvironment);375    endNextTone(this.audioEnvironment);376    endNextTone(this.audioEnvironment);377    endNextTone(this.audioEnvironment);378    endNextTone(this.audioEnvironment);379    endNextTone(this.audioEnvironment);380    expect(scheduledTones(this.audioEnvironment).length).toEqual(9);381  });382  it("should not schedule additional silent tone after last completes", function () {383    setPlayDelaySeconds(this.player, 5);384    setCurrentTimeSeconds(this.audioEnvironment, 6);385    play(386      this.player,387      [Color.red, Color.green, Color.blue, Color.yellow],388      7000,389      8000390    );391    endNextTone(this.audioEnvironment);392    endNextTone(this.audioEnvironment);393    endNextTone(this.audioEnvironment);394    endNextTone(this.audioEnvironment);395    endNextTone(this.audioEnvironment);396    endNextTone(this.audioEnvironment);397    endNextTone(this.audioEnvironment);398    endNextTone(this.audioEnvironment);399    endNextTone(this.audioEnvironment);400    expect(scheduledTones(this.audioEnvironment).length).toEqual(9);401  });402  it("should notify when first color tone starts", function () {403    const listener = new ColorToneEventListenerStub();404    this.player.subscribe(listener);405    setPlayDelaySeconds(this.player, 5);406    setCurrentTimeSeconds(this.audioEnvironment, 6);407    play(408      this.player,409      [Color.red, Color.green, Color.blue, Color.yellow],410      7000,411      8000412    );413    expectFalse(notifiedThatRedToneStarted(listener));414    endNextTone(this.audioEnvironment);415    expectTrue(notifiedThatRedToneStarted(listener));416  });417  it("should notify when second color tone starts", function () {418    const listener = new ColorToneEventListenerStub();419    this.player.subscribe(listener);420    setPlayDelaySeconds(this.player, 5);421    setCurrentTimeSeconds(this.audioEnvironment, 6);422    play(423      this.player,424      [Color.red, Color.green, Color.blue, Color.yellow],425      7000,426      8000427    );428    endNextTone(this.audioEnvironment);429    endNextTone(this.audioEnvironment);430    expectFalse(notifiedThatGreenToneStarted(listener));431    endNextTone(this.audioEnvironment);432    expectTrue(notifiedThatGreenToneStarted(listener));433  });434  it("should notify when third color tone starts", function () {435    const listener = new ColorToneEventListenerStub();436    this.player.subscribe(listener);437    setPlayDelaySeconds(this.player, 5);438    setCurrentTimeSeconds(this.audioEnvironment, 6);439    play(440      this.player,441      [Color.red, Color.green, Color.blue, Color.yellow],442      7000,443      8000444    );445    endNextTone(this.audioEnvironment);446    endNextTone(this.audioEnvironment);447    endNextTone(this.audioEnvironment);448    endNextTone(this.audioEnvironment);449    expectFalse(notifiedThatBlueToneStarted(listener));450    endNextTone(this.audioEnvironment);451    expectTrue(notifiedThatBlueToneStarted(listener));452  });453  it("should notify when fourth color tone starts", function () {454    const listener = new ColorToneEventListenerStub();455    this.player.subscribe(listener);456    setPlayDelaySeconds(this.player, 5);457    setCurrentTimeSeconds(this.audioEnvironment, 6);458    play(459      this.player,460      [Color.red, Color.green, Color.blue, Color.yellow],461      7000,462      8000463    );464    endNextTone(this.audioEnvironment);465    endNextTone(this.audioEnvironment);466    endNextTone(this.audioEnvironment);467    endNextTone(this.audioEnvironment);468    endNextTone(this.audioEnvironment);469    endNextTone(this.audioEnvironment);470    expectFalse(notifiedThatYellowToneStarted(listener));471    endNextTone(this.audioEnvironment);472    expectTrue(notifiedThatYellowToneStarted(listener));473  });474  it("should notify when first color tone ends", function () {475    const listener = new ColorToneEventListenerStub();476    this.player.subscribe(listener);477    setPlayDelaySeconds(this.player, 5);478    setCurrentTimeSeconds(this.audioEnvironment, 6);479    play(480      this.player,481      [Color.red, Color.green, Color.blue, Color.yellow],482      7000,483      8000484    );485    endNextTone(this.audioEnvironment);486    expectFalse(notifiedThatRedToneEnded(listener));487    endNextTone(this.audioEnvironment);488    expectTrue(notifiedThatRedToneEnded(listener));489  });490  it("should notify when second color tone ends", function () {491    const listener = new ColorToneEventListenerStub();492    this.player.subscribe(listener);493    setPlayDelaySeconds(this.player, 5);494    setCurrentTimeSeconds(this.audioEnvironment, 6);495    play(496      this.player,497      [Color.red, Color.green, Color.blue, Color.yellow],498      7000,499      8000500    );501    endNextTone(this.audioEnvironment);502    endNextTone(this.audioEnvironment);503    endNextTone(this.audioEnvironment);504    expectFalse(notifiedThatGreenToneEnded(listener));505    endNextTone(this.audioEnvironment);506    expectTrue(notifiedThatGreenToneEnded(listener));507  });508  it("should notify when third color tone ends", function () {509    const listener = new ColorToneEventListenerStub();510    this.player.subscribe(listener);511    setPlayDelaySeconds(this.player, 5);512    setCurrentTimeSeconds(this.audioEnvironment, 6);513    play(514      this.player,515      [Color.red, Color.green, Color.blue, Color.yellow],516      7000,517      8000518    );519    endNextTone(this.audioEnvironment);520    endNextTone(this.audioEnvironment);521    endNextTone(this.audioEnvironment);522    endNextTone(this.audioEnvironment);523    endNextTone(this.audioEnvironment);524    expectFalse(notifiedThatBlueToneEnded(listener));525    endNextTone(this.audioEnvironment);526    expectTrue(notifiedThatBlueToneEnded(listener));527  });528  it("should notify when fourth color tone ends", function () {529    const listener = new ColorToneEventListenerStub();530    this.player.subscribe(listener);531    setPlayDelaySeconds(this.player, 5);532    setCurrentTimeSeconds(this.audioEnvironment, 6);533    play(534      this.player,535      [Color.red, Color.green, Color.blue, Color.yellow],536      7000,537      8000538    );539    endNextTone(this.audioEnvironment);540    endNextTone(this.audioEnvironment);541    endNextTone(this.audioEnvironment);542    endNextTone(this.audioEnvironment);543    endNextTone(this.audioEnvironment);544    endNextTone(this.audioEnvironment);545    endNextTone(this.audioEnvironment);546    expectFalse(notifiedThatYellowToneEnded(listener));547    endNextTone(this.audioEnvironment);548    expectTrue(notifiedThatYellowToneEnded(listener));549  });550  it("should notify when playing ends", function () {551    const listener = new ColorToneEventListenerStub();552    this.player.subscribe(listener);553    setPlayDelaySeconds(this.player, 5);554    setCurrentTimeSeconds(this.audioEnvironment, 6);555    play(556      this.player,557      [Color.red, Color.green, Color.blue, Color.yellow],558      7000,559      8000560    );561    endNextTone(this.audioEnvironment);562    endNextTone(this.audioEnvironment);563    endNextTone(this.audioEnvironment);564    endNextTone(this.audioEnvironment);565    endNextTone(this.audioEnvironment);566    endNextTone(this.audioEnvironment);567    endNextTone(this.audioEnvironment);568    endNextTone(this.audioEnvironment);569    expectFalse(notifiedThatToneSeriesEnded(listener));570    endNextTone(this.audioEnvironment);571    expectTrue(notifiedThatToneSeriesEnded(listener));572  });573  it("is playing until playing ends", function () {574    expectFalse(playing(this.player));575    play(576      this.player,577      [Color.red, Color.green, Color.blue, Color.yellow],578      7000,579      8000580    );581    expectTrue(playing(this.player));582    endNextTone(this.audioEnvironment);583    endNextTone(this.audioEnvironment);584    endNextTone(this.audioEnvironment);585    endNextTone(this.audioEnvironment);586    endNextTone(this.audioEnvironment);587    endNextTone(this.audioEnvironment);588    endNextTone(this.audioEnvironment);589    endNextTone(this.audioEnvironment);590    expectTrue(playing(this.player));591    endNextTone(this.audioEnvironment);592    expectFalse(playing(this.player));593  });594  it("should notify when correct color tone starts", function () {595    const listener = new ColorToneEventListenerStub();596    this.player.subscribe(listener);597    playCorrectBlueTone(this.player, 7000);598    expectFalse(notifiedThatCorrectBlueToneStarted(listener));599    endNextTone(this.audioEnvironment);600    expectTrue(notifiedThatCorrectBlueToneStarted(listener));601  });602  it("should notify when correct color tone ends", function () {603    const listener = new ColorToneEventListenerStub();604    this.player.subscribe(listener);605    playCorrectBlueTone(this.player, 7000);606    endNextTone(this.audioEnvironment);607    expectFalse(notifiedThatCorrectBlueToneEnded(listener));608    endNextTone(this.audioEnvironment);609    expectTrue(notifiedThatCorrectBlueToneEnded(listener));610  });611  it("should notify when incorrect color tone starts", function () {612    const listener = new ColorToneEventListenerStub();613    this.player.subscribe(listener);614    playIncorrectBlueTone(this.player, 7000);615    expectFalse(notifiedThatIncorrectBlueToneStarted(listener));616    endNextTone(this.audioEnvironment);617    expectTrue(notifiedThatIncorrectBlueToneStarted(listener));618  });619  it("should notify when incorrect color tone ends", function () {620    const listener = new ColorToneEventListenerStub();621    this.player.subscribe(listener);622    playIncorrectBlueTone(this.player, 7000);623    endNextTone(this.audioEnvironment);624    expectFalse(notifiedThatIncorrectBlueToneEnded(listener));625    endNextTone(this.audioEnvironment);626    expectTrue(notifiedThatIncorrectBlueToneEnded(listener));627  });...environmentVariableCollection.test.ts
Source:environmentVariableCollection.test.ts  
1/*---------------------------------------------------------------------------------------------2 *  Copyright (c) Microsoft Corporation. All rights reserved.3 *  Licensed under the MIT License. See License.txt in the project root for license information.4 *--------------------------------------------------------------------------------------------*/5import { deepStrictEqual, strictEqual } from 'assert';6import { EnvironmentVariableMutatorType } from 'vs/workbench/contrib/terminal/common/environmentVariable';7import { IProcessEnvironment, isWindows } from 'vs/base/common/platform';8import { MergedEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariableCollection';9import { deserializeEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariableShared';10suite('EnvironmentVariable - MergedEnvironmentVariableCollection', () => {11	suite('ctor', () => {12		test('Should keep entries that come after a Prepend or Append type mutators', () => {13			const merged = new MergedEnvironmentVariableCollection(new Map([14				['ext1', {15					map: deserializeEnvironmentVariableCollection([16						['A', { value: 'a1', type: EnvironmentVariableMutatorType.Prepend }]17					])18				}],19				['ext2', {20					map: deserializeEnvironmentVariableCollection([21						['A', { value: 'a2', type: EnvironmentVariableMutatorType.Append }]22					])23				}],24				['ext3', {25					map: deserializeEnvironmentVariableCollection([26						['A', { value: 'a3', type: EnvironmentVariableMutatorType.Prepend }]27					])28				}],29				['ext4', {30					map: deserializeEnvironmentVariableCollection([31						['A', { value: 'a4', type: EnvironmentVariableMutatorType.Append }]32					])33				}]34			]));35			deepStrictEqual([...merged.map.entries()], [36				['A', [37					{ extensionIdentifier: 'ext4', type: EnvironmentVariableMutatorType.Append, value: 'a4' },38					{ extensionIdentifier: 'ext3', type: EnvironmentVariableMutatorType.Prepend, value: 'a3' },39					{ extensionIdentifier: 'ext2', type: EnvironmentVariableMutatorType.Append, value: 'a2' },40					{ extensionIdentifier: 'ext1', type: EnvironmentVariableMutatorType.Prepend, value: 'a1' }41				]]42			]);43		});44		test('Should remove entries that come after a Replace type mutator', () => {45			const merged = new MergedEnvironmentVariableCollection(new Map([46				['ext1', {47					map: deserializeEnvironmentVariableCollection([48						['A', { value: 'a1', type: EnvironmentVariableMutatorType.Prepend }]49					])50				}],51				['ext2', {52					map: deserializeEnvironmentVariableCollection([53						['A', { value: 'a2', type: EnvironmentVariableMutatorType.Append }]54					])55				}],56				['ext3', {57					map: deserializeEnvironmentVariableCollection([58						['A', { value: 'a3', type: EnvironmentVariableMutatorType.Replace }]59					])60				}],61				['ext4', {62					map: deserializeEnvironmentVariableCollection([63						['A', { value: 'a4', type: EnvironmentVariableMutatorType.Append }]64					])65				}]66			]));67			deepStrictEqual([...merged.map.entries()], [68				['A', [69					{ extensionIdentifier: 'ext3', type: EnvironmentVariableMutatorType.Replace, value: 'a3' },70					{ extensionIdentifier: 'ext2', type: EnvironmentVariableMutatorType.Append, value: 'a2' },71					{ extensionIdentifier: 'ext1', type: EnvironmentVariableMutatorType.Prepend, value: 'a1' }72				]]73			], 'The ext4 entry should be removed as it comes after a Replace');74		});75	});76	suite('applyToProcessEnvironment', () => {77		test('should apply the collection to an environment', () => {78			const merged = new MergedEnvironmentVariableCollection(new Map([79				['ext', {80					map: deserializeEnvironmentVariableCollection([81						['A', { value: 'a', type: EnvironmentVariableMutatorType.Replace }],82						['B', { value: 'b', type: EnvironmentVariableMutatorType.Append }],83						['C', { value: 'c', type: EnvironmentVariableMutatorType.Prepend }]84					])85				}]86			]));87			const env: IProcessEnvironment = {88				A: 'foo',89				B: 'bar',90				C: 'baz'91			};92			merged.applyToProcessEnvironment(env);93			deepStrictEqual(env, {94				A: 'a',95				B: 'barb',96				C: 'cbaz'97			});98		});99		test('should apply the collection to environment entries with no values', () => {100			const merged = new MergedEnvironmentVariableCollection(new Map([101				['ext', {102					map: deserializeEnvironmentVariableCollection([103						['A', { value: 'a', type: EnvironmentVariableMutatorType.Replace }],104						['B', { value: 'b', type: EnvironmentVariableMutatorType.Append }],105						['C', { value: 'c', type: EnvironmentVariableMutatorType.Prepend }]106					])107				}]108			]));109			const env: IProcessEnvironment = {};110			merged.applyToProcessEnvironment(env);111			deepStrictEqual(env, {112				A: 'a',113				B: 'b',114				C: 'c'115			});116		});117		test('should apply to variable case insensitively on Windows only', () => {118			const merged = new MergedEnvironmentVariableCollection(new Map([119				['ext', {120					map: deserializeEnvironmentVariableCollection([121						['a', { value: 'a', type: EnvironmentVariableMutatorType.Replace }],122						['b', { value: 'b', type: EnvironmentVariableMutatorType.Append }],123						['c', { value: 'c', type: EnvironmentVariableMutatorType.Prepend }]124					])125				}]126			]));127			const env: IProcessEnvironment = {128				A: 'A',129				B: 'B',130				C: 'C'131			};132			merged.applyToProcessEnvironment(env);133			if (isWindows) {134				deepStrictEqual(env, {135					A: 'a',136					B: 'Bb',137					C: 'cC'138				});139			} else {140				deepStrictEqual(env, {141					a: 'a',142					A: 'A',143					b: 'b',144					B: 'B',145					c: 'c',146					C: 'C'147				});148			}149		});150	});151	suite('diff', () => {152		test('should return undefined when collectinos are the same', () => {153			const merged1 = new MergedEnvironmentVariableCollection(new Map([154				['ext1', {155					map: deserializeEnvironmentVariableCollection([156						['A', { value: 'a', type: EnvironmentVariableMutatorType.Replace }]157					])158				}]159			]));160			const merged2 = new MergedEnvironmentVariableCollection(new Map([161				['ext1', {162					map: deserializeEnvironmentVariableCollection([163						['A', { value: 'a', type: EnvironmentVariableMutatorType.Replace }]164					])165				}]166			]));167			const diff = merged1.diff(merged2);168			strictEqual(diff, undefined);169		});170		test('should generate added diffs from when the first entry is added', () => {171			const merged1 = new MergedEnvironmentVariableCollection(new Map([]));172			const merged2 = new MergedEnvironmentVariableCollection(new Map([173				['ext1', {174					map: deserializeEnvironmentVariableCollection([175						['A', { value: 'a', type: EnvironmentVariableMutatorType.Replace }]176					])177				}]178			]));179			const diff = merged1.diff(merged2)!;180			strictEqual(diff.changed.size, 0);181			strictEqual(diff.removed.size, 0);182			const entries = [...diff.added.entries()];183			deepStrictEqual(entries, [184				['A', [{ extensionIdentifier: 'ext1', value: 'a', type: EnvironmentVariableMutatorType.Replace }]]185			]);186		});187		test('should generate added diffs from the same extension', () => {188			const merged1 = new MergedEnvironmentVariableCollection(new Map([189				['ext1', {190					map: deserializeEnvironmentVariableCollection([191						['A', { value: 'a', type: EnvironmentVariableMutatorType.Replace }]192					])193				}]194			]));195			const merged2 = new MergedEnvironmentVariableCollection(new Map([196				['ext1', {197					map: deserializeEnvironmentVariableCollection([198						['A', { value: 'a', type: EnvironmentVariableMutatorType.Replace }],199						['B', { value: 'b', type: EnvironmentVariableMutatorType.Append }]200					])201				}]202			]));203			const diff = merged1.diff(merged2)!;204			strictEqual(diff.changed.size, 0);205			strictEqual(diff.removed.size, 0);206			const entries = [...diff.added.entries()];207			deepStrictEqual(entries, [208				['B', [{ extensionIdentifier: 'ext1', value: 'b', type: EnvironmentVariableMutatorType.Append }]]209			]);210		});211		test('should generate added diffs from a different extension', () => {212			const merged1 = new MergedEnvironmentVariableCollection(new Map([213				['ext1', {214					map: deserializeEnvironmentVariableCollection([215						['A', { value: 'a1', type: EnvironmentVariableMutatorType.Prepend }]216					])217				}]218			]));219			const merged2 = new MergedEnvironmentVariableCollection(new Map([220				['ext2', {221					map: deserializeEnvironmentVariableCollection([222						['A', { value: 'a2', type: EnvironmentVariableMutatorType.Append }]223					])224				}],225				['ext1', {226					map: deserializeEnvironmentVariableCollection([227						['A', { value: 'a1', type: EnvironmentVariableMutatorType.Prepend }]228					])229				}]230			]));231			const diff = merged1.diff(merged2)!;232			strictEqual(diff.changed.size, 0);233			strictEqual(diff.removed.size, 0);234			deepStrictEqual([...diff.added.entries()], [235				['A', [{ extensionIdentifier: 'ext2', value: 'a2', type: EnvironmentVariableMutatorType.Append }]]236			]);237			const merged3 = new MergedEnvironmentVariableCollection(new Map([238				['ext1', {239					map: deserializeEnvironmentVariableCollection([240						['A', { value: 'a1', type: EnvironmentVariableMutatorType.Prepend }]241					])242				}],243				// This entry should get removed244				['ext2', {245					map: deserializeEnvironmentVariableCollection([246						['A', { value: 'a2', type: EnvironmentVariableMutatorType.Append }]247					])248				}]249			]));250			const diff2 = merged1.diff(merged3)!;251			strictEqual(diff2.changed.size, 0);252			strictEqual(diff2.removed.size, 0);253			deepStrictEqual([...diff.added.entries()], [...diff2.added.entries()], 'Swapping the order of the entries in the other collection should yield the same result');254		});255		test('should remove entries in the diff that come after a Replace', () => {256			const merged1 = new MergedEnvironmentVariableCollection(new Map([257				['ext1', {258					map: deserializeEnvironmentVariableCollection([259						['A', { value: 'a1', type: EnvironmentVariableMutatorType.Replace }]260					])261				}]262			]));263			const merged4 = new MergedEnvironmentVariableCollection(new Map([264				['ext1', {265					map: deserializeEnvironmentVariableCollection([266						['A', { value: 'a1', type: EnvironmentVariableMutatorType.Replace }]267					])268				}],269				// This entry should get removed as it comes after a replace270				['ext2', {271					map: deserializeEnvironmentVariableCollection([272						['A', { value: 'a2', type: EnvironmentVariableMutatorType.Append }]273					])274				}]275			]));276			const diff = merged1.diff(merged4);277			strictEqual(diff, undefined, 'Replace should ignore any entries after it');278		});279		test('should generate removed diffs', () => {280			const merged1 = new MergedEnvironmentVariableCollection(new Map([281				['ext1', {282					map: deserializeEnvironmentVariableCollection([283						['A', { value: 'a', type: EnvironmentVariableMutatorType.Replace }],284						['B', { value: 'b', type: EnvironmentVariableMutatorType.Replace }]285					])286				}]287			]));288			const merged2 = new MergedEnvironmentVariableCollection(new Map([289				['ext1', {290					map: deserializeEnvironmentVariableCollection([291						['A', { value: 'a', type: EnvironmentVariableMutatorType.Replace }]292					])293				}]294			]));295			const diff = merged1.diff(merged2)!;296			strictEqual(diff.changed.size, 0);297			strictEqual(diff.added.size, 0);298			deepStrictEqual([...diff.removed.entries()], [299				['B', [{ extensionIdentifier: 'ext1', value: 'b', type: EnvironmentVariableMutatorType.Replace }]]300			]);301		});302		test('should generate changed diffs', () => {303			const merged1 = new MergedEnvironmentVariableCollection(new Map([304				['ext1', {305					map: deserializeEnvironmentVariableCollection([306						['A', { value: 'a1', type: EnvironmentVariableMutatorType.Replace }],307						['B', { value: 'b', type: EnvironmentVariableMutatorType.Replace }]308					])309				}]310			]));311			const merged2 = new MergedEnvironmentVariableCollection(new Map([312				['ext1', {313					map: deserializeEnvironmentVariableCollection([314						['A', { value: 'a2', type: EnvironmentVariableMutatorType.Replace }],315						['B', { value: 'b', type: EnvironmentVariableMutatorType.Append }]316					])317				}]318			]));319			const diff = merged1.diff(merged2)!;320			strictEqual(diff.added.size, 0);321			strictEqual(diff.removed.size, 0);322			deepStrictEqual([...diff.changed.entries()], [323				['A', [{ extensionIdentifier: 'ext1', value: 'a2', type: EnvironmentVariableMutatorType.Replace }]],324				['B', [{ extensionIdentifier: 'ext1', value: 'b', type: EnvironmentVariableMutatorType.Append }]]325			]);326		});327		test('should generate diffs with added, changed and removed', () => {328			const merged1 = new MergedEnvironmentVariableCollection(new Map([329				['ext1', {330					map: deserializeEnvironmentVariableCollection([331						['A', { value: 'a1', type: EnvironmentVariableMutatorType.Replace }],332						['B', { value: 'b', type: EnvironmentVariableMutatorType.Prepend }]333					])334				}]335			]));336			const merged2 = new MergedEnvironmentVariableCollection(new Map([337				['ext1', {338					map: deserializeEnvironmentVariableCollection([339						['A', { value: 'a2', type: EnvironmentVariableMutatorType.Replace }],340						['C', { value: 'c', type: EnvironmentVariableMutatorType.Append }]341					])342				}]343			]));344			const diff = merged1.diff(merged2)!;345			deepStrictEqual([...diff.added.entries()], [346				['C', [{ extensionIdentifier: 'ext1', value: 'c', type: EnvironmentVariableMutatorType.Append }]],347			]);348			deepStrictEqual([...diff.removed.entries()], [349				['B', [{ extensionIdentifier: 'ext1', value: 'b', type: EnvironmentVariableMutatorType.Prepend }]]350			]);351			deepStrictEqual([...diff.changed.entries()], [352				['A', [{ extensionIdentifier: 'ext1', value: 'a2', type: EnvironmentVariableMutatorType.Replace }]]353			]);354		});355	});...environmentVariableService.test.ts
Source:environmentVariableService.test.ts  
1/*---------------------------------------------------------------------------------------------2 *  Copyright (c) Microsoft Corporation. All rights reserved.3 *  Licensed under the MIT License. See License.txt in the project root for license information.4 *--------------------------------------------------------------------------------------------*/5import { deepStrictEqual } from 'assert';6import { TestExtensionService, TestStorageService } from 'vs/workbench/test/common/workbenchTestServices';7import { EnvironmentVariableService } from 'vs/workbench/contrib/terminal/common/environmentVariableService';8import { EnvironmentVariableMutatorType, IEnvironmentVariableMutator } from 'vs/workbench/contrib/terminal/common/environmentVariable';9import { IStorageService } from 'vs/platform/storage/common/storage';10import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';11import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';12import { Emitter } from 'vs/base/common/event';13import { IProcessEnvironment } from 'vs/base/common/platform';14class TestEnvironmentVariableService extends EnvironmentVariableService {15	persistCollections(): void { this._persistCollections(); }16	notifyCollectionUpdates(): void { this._notifyCollectionUpdates(); }17}18suite('EnvironmentVariable - EnvironmentVariableService', () => {19	let instantiationService: TestInstantiationService;20	let environmentVariableService: TestEnvironmentVariableService;21	let storageService: TestStorageService;22	let changeExtensionsEvent: Emitter<void>;23	setup(() => {24		changeExtensionsEvent = new Emitter<void>();25		instantiationService = new TestInstantiationService();26		instantiationService.stub(IExtensionService, TestExtensionService);27		storageService = new TestStorageService();28		instantiationService.stub(IStorageService, storageService);29		instantiationService.stub(IExtensionService, TestExtensionService);30		instantiationService.stub(IExtensionService, 'onDidChangeExtensions', changeExtensionsEvent.event);31		instantiationService.stub(IExtensionService, 'getExtensions', [32			{ identifier: { value: 'ext1' } },33			{ identifier: { value: 'ext2' } },34			{ identifier: { value: 'ext3' } }35		]);36		environmentVariableService = instantiationService.createInstance(TestEnvironmentVariableService);37	});38	test('should persist collections to the storage service and be able to restore from them', () => {39		const collection = new Map<string, IEnvironmentVariableMutator>();40		collection.set('A', { value: 'a', type: EnvironmentVariableMutatorType.Replace });41		collection.set('B', { value: 'b', type: EnvironmentVariableMutatorType.Append });42		collection.set('C', { value: 'c', type: EnvironmentVariableMutatorType.Prepend });43		environmentVariableService.set('ext1', { map: collection, persistent: true });44		deepStrictEqual([...environmentVariableService.mergedCollection.map.entries()], [45			['A', [{ extensionIdentifier: 'ext1', type: EnvironmentVariableMutatorType.Replace, value: 'a' }]],46			['B', [{ extensionIdentifier: 'ext1', type: EnvironmentVariableMutatorType.Append, value: 'b' }]],47			['C', [{ extensionIdentifier: 'ext1', type: EnvironmentVariableMutatorType.Prepend, value: 'c' }]]48		]);49		// Persist with old service, create a new service with the same storage service to verify restore50		environmentVariableService.persistCollections();51		const service2: TestEnvironmentVariableService = instantiationService.createInstance(TestEnvironmentVariableService);52		deepStrictEqual([...service2.mergedCollection.map.entries()], [53			['A', [{ extensionIdentifier: 'ext1', type: EnvironmentVariableMutatorType.Replace, value: 'a' }]],54			['B', [{ extensionIdentifier: 'ext1', type: EnvironmentVariableMutatorType.Append, value: 'b' }]],55			['C', [{ extensionIdentifier: 'ext1', type: EnvironmentVariableMutatorType.Prepend, value: 'c' }]]56		]);57	});58	suite('mergedCollection', () => {59		test('should overwrite any other variable with the first extension that replaces', () => {60			const collection1 = new Map<string, IEnvironmentVariableMutator>();61			const collection2 = new Map<string, IEnvironmentVariableMutator>();62			const collection3 = new Map<string, IEnvironmentVariableMutator>();63			collection1.set('A', { value: 'a1', type: EnvironmentVariableMutatorType.Append });64			collection1.set('B', { value: 'b1', type: EnvironmentVariableMutatorType.Replace });65			collection2.set('A', { value: 'a2', type: EnvironmentVariableMutatorType.Replace });66			collection2.set('B', { value: 'b2', type: EnvironmentVariableMutatorType.Append });67			collection3.set('A', { value: 'a3', type: EnvironmentVariableMutatorType.Prepend });68			collection3.set('B', { value: 'b3', type: EnvironmentVariableMutatorType.Replace });69			environmentVariableService.set('ext1', { map: collection1, persistent: true });70			environmentVariableService.set('ext2', { map: collection2, persistent: true });71			environmentVariableService.set('ext3', { map: collection3, persistent: true });72			deepStrictEqual([...environmentVariableService.mergedCollection.map.entries()], [73				['A', [74					{ extensionIdentifier: 'ext2', type: EnvironmentVariableMutatorType.Replace, value: 'a2' },75					{ extensionIdentifier: 'ext1', type: EnvironmentVariableMutatorType.Append, value: 'a1' }76				]],77				['B', [{ extensionIdentifier: 'ext1', type: EnvironmentVariableMutatorType.Replace, value: 'b1' }]]78			]);79		});80		test('should correctly apply the environment values from multiple extension contributions in the correct order', () => {81			const collection1 = new Map<string, IEnvironmentVariableMutator>();82			const collection2 = new Map<string, IEnvironmentVariableMutator>();83			const collection3 = new Map<string, IEnvironmentVariableMutator>();84			collection1.set('A', { value: ':a1', type: EnvironmentVariableMutatorType.Append });85			collection2.set('A', { value: 'a2:', type: EnvironmentVariableMutatorType.Prepend });86			collection3.set('A', { value: 'a3', type: EnvironmentVariableMutatorType.Replace });87			environmentVariableService.set('ext1', { map: collection1, persistent: true });88			environmentVariableService.set('ext2', { map: collection2, persistent: true });89			environmentVariableService.set('ext3', { map: collection3, persistent: true });90			// The entries should be ordered in the order they are applied91			deepStrictEqual([...environmentVariableService.mergedCollection.map.entries()], [92				['A', [93					{ extensionIdentifier: 'ext3', type: EnvironmentVariableMutatorType.Replace, value: 'a3' },94					{ extensionIdentifier: 'ext2', type: EnvironmentVariableMutatorType.Prepend, value: 'a2:' },95					{ extensionIdentifier: 'ext1', type: EnvironmentVariableMutatorType.Append, value: ':a1' }96				]]97			]);98			// Verify the entries get applied to the environment as expected99			const env: IProcessEnvironment = { A: 'foo' };100			environmentVariableService.mergedCollection.applyToProcessEnvironment(env);101			deepStrictEqual(env, { A: 'a2:a3:a1' });102		});103	});...environment.test.ts
Source:environment.test.ts  
1import { beforeAll, beforeEach, describe, expect, it, jest } from '@jest/globals';2import _enquirer from 'enquirer';3import { Mock, MockedClass } from 'jest-mock';4import { globalBeforeAll, globalBeforeEach } from '../../jest/before';5import type { Database } from '../index';6import { emptyDb } from '../index';7import { loadEnvironment, promptEnvironment } from './environment';8import type { Environment, Workspace } from './types';9import { generateIdIsh } from './util';10jest.mock('enquirer');11const enquirer = _enquirer as MockedClass<typeof _enquirer> & {12  __mockPromptRun: (str: string) => void;13  // eslint-disable-next-line @typescript-eslint/no-explicit-any -- missing types from enquirer14  __constructorMock: Mock;15};16describe('Environment', () => {17  beforeAll(() => {18    globalBeforeAll();19  });20  beforeEach(() => {21    globalBeforeEach();22  });23  let db: Database = emptyDb();24  const workspace = {25    _id: 'wrk_1234567890',26    name: 'workspace name',27  } as Workspace;28  const environment = {29    _id: 'env_1234567890',30    name: 'base env',31    parentId: workspace._id,32  } as Environment;33  const subEnvironment = {34    _id: 'env_env_1234567890',35    name: 'sub env',36    parentId: environment._id,37  } as Environment;38  beforeEach(() => {39    db = emptyDb();40    const dummySubEnv = {41      _id: 'env_env_dummy',42      name: 'dummy sub env',43      parentId: environment._id,44    } as Environment;45    db.Workspace.push(workspace);46    db.Environment.push(environment);47    db.Environment.push(subEnvironment);48    db.Environment.push(dummySubEnv);49    jest.clearAllMocks();50  });51  describe('promptEnvironment()', () => {52    it('should return null if ci', () => {53      expect(promptEnvironment(db, true, workspace._id)).resolves.toBeNull();54    });55    it('should return null if no environments exist', () => {56      db.Environment = [];57      expect(promptEnvironment(db, false, workspace._id)).resolves.toBeNull();58    });59    it('should throw error if base env for workspace not found', () => {60      expect(promptEnvironment(db, false, 'workspace-not-found')).rejects.toThrowError();61    });62    it('should throw error if multiple base env for workspace found', () => {63      db.Environment.push({ ...environment });64      expect(promptEnvironment(db, false, workspace._id)).rejects.toThrowError();65    });66    it('should load sub environment after prompt result', async () => {67      enquirer.__mockPromptRun('environment - env_env_123456');68      expect(promptEnvironment(db, false, workspace._id)).resolves.toBe(subEnvironment);69    });70    it('should match snapshot of autocomplete config', async () => {71      await promptEnvironment(db, false, workspace._id);72      expect(enquirer.__constructorMock.mock.calls[0][0]).toMatchSnapshot();73    });74  });75  describe('loadEnvironment()', () => {76    it('should return null if no environments exist', () => {77      db.Environment = [];78      expect(loadEnvironment(db, workspace._id, environment._id)).toBeNull();79    });80    it('should throw error if base env for workspace not found', () => {81      expect(() => loadEnvironment(db, 'workspace-not-found', environment._id)).toThrowError();82    });83    it('should throw error if multiple base env for workspace found', () => {84      db.Environment.push({ ...environment });85      expect(() => loadEnvironment(db, workspace._id, environment._id)).toThrowError();86    });87    it.each([generateIdIsh(subEnvironment), subEnvironment._id, subEnvironment.name])(88      'should return the sub environment if matched with id: %s',89      () => {90        expect(loadEnvironment(db, workspace._id, subEnvironment._id)).toBe(subEnvironment);91      },92    );93    it('should return the base environment if env id not specified', () => {94      expect(loadEnvironment(db, workspace._id)).toBe(environment);95    });96    it('should return the base environment if no sub envs exist', () => {97      db.Environment = [environment];98      expect(loadEnvironment(db, workspace._id)).toBe(environment);99    });100    it('should throw error sub env not found', () => {101      db.Environment = [environment];102      expect(() => loadEnvironment(db, workspace._id, subEnvironment._id)).toThrowError();103    });104  });...Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!
